2015-09-09 62 views
0

說我有:映射SharePoint列表項的C#類

public class SPListItem 
{ 
    public override object this[string fieldName] 
    { 
     get 
     { 
     return this.GetValue(fieldName); 
     } 
     set 
     { 
     this.SetValue(fieldName, value, !this.HasExternalDataSource); 
     } 
    } 
} 

public class Bar 
{ 
    public int Prop1 { get; set; } 
    public int Prop2 { get; set; } 
    public int Prop3 { get; set; } 
} 

有什麼辦法,我可以這樣做:

var fooInst = new SPListItem(); 
Bar barInst = (Bar)fooInst // or maybe Bar.FromFoo(Foo f) if handling the cast is not possible 

,然後有:

barInst.Prop1給我相當於:

fooInst["Prop"];

沒有爲Bar中的每個屬性實現getter和setter?

+1

你能在你的問題的文字說明你正在試圖解決什麼問題?如果它不繼承或不提供顯式轉換運算符,則不能投射,因此您必須以這種或那種方式映射屬性。 AutoMapper可以爲你做到這一點。 – CodeCaster

+0

[ExpandoObject(https://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx)就是這樣做的... – m0sa

+0

這是一個錯誤的問題,並沒有任何與鑄造。你問的是如何將POCO的值複製到* SharePoint *服務器端SPListItem對象。 Expando和其他任何對象都無法提供幫助。字段名稱可能與特性的* not *名稱不同。爲什麼不使用LINQ to SharePoint來定義映射? –

回答

0

Aaaaaand,在這裏我們去。這個類從你的列表中生成實體。 來源:https://justsharepointthings.wordpress.com/2015/09/10/sharepoint-generate-c-poco-classes-from-an-existing-definition/

using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using Microsoft.SharePoint; 

namespace Code_Generation { 
    /// <summary> 
    /// Generates List object entities from a site connection. 
    /// </summary> 
    public class SPListPocoGenerator { 
     string parentDir = "GeneratedListPOCO/"; 
     string hiddenDir = "GeneratedListPOCO/HiddenLists/"; 

     private class PropertyString { 
      private string _propStr; 

      public PropertyString(string propStr) { 
       _propStr = propStr; 
       _properties = new Dictionary < string, string >(); 
      } 

      private Dictionary < string, string > _properties; 
      public string this[string key] { 
       get { 
        return _properties.ContainsKey(key) ? _properties[key] : string.Empty; 
       } 
       set { 
        if (_properties.ContainsKey(key)) { 
         _properties[key] = value; 
        } else { 
         _properties.Add(key, value); 
        } 
       } 
      } 



      /// <summary> 
      /// Replaces properties in the format {{propertyName}} in the source string with values from KeyValuePairPropertiesDictionarysupplied dictionary.nce you've set a property it's replaced in the string and you 
      /// </summary> 
      /// <param name="originalStr"></param> 
      /// <param name="keyValuePairPropertiesDictionary"></param> 
      /// <returns></returns> 
      public override string ToString() { 
       string modifiedStr = _propStr; 
       foreach(var keyvaluePair in _properties) { 
        modifiedStr = modifiedStr.Replace("{{" + keyvaluePair.Key + "}}", keyvaluePair.Value); 
       } 

       return modifiedStr; 
      } 
     } 



     public string _classDefinitionStr = @ 
     " 
using System; 
using Microsoft.SharePoint; 

public class {{EntityName}} 
{ 
    private SPListItem listItem; 
    public {{EntityName}}_InternalProperties InternalProperties 
    { 
     get; private set; 
    } 

    public {{EntityName}}(SPListItem li) 
    { 
     this.listItem = li; 
     this.InternalProperties = new {{EntityName}}_InternalProperties(this.listItem); 
    } 

    {{PropertySections}} 
    public class {{EntityName}}_InternalProperties 
    { 
     private SPListItem listItem; 

     public {{EntityName}}_InternalProperties(SPListItem li) 
     { 
      this.listItem = li; 
     } 

     {{HiddenPropertySections}} 
     {{InternalPropertySections}} 
    }  
}"; 

     private const string _propertySectionStr = "\n\n\t" + @ 
     "public {{PropertyType}} {{PropertyName}} 
    { get { return listItem[Guid.Parse(" 
     "{{PropertyId}}" 
     ")] as {{PropertyType}}; } 
     set { listItem[Guid.Parse(" 
     "{{PropertyId}}" 
     ")] = value; }}"; 

     /// <summary> 
     /// Gets string identifying the field type 
     /// </summary> 
     /// <param name="field"></param> 
     /// <returns></returns> 
     private string GetSafeTypeName(SPField field) { 
      if (field.FieldValueType == null) { 
       return "object"; //Not going to try to parse it further, this is enough. 
      } 

      var type = field.FieldValueType; 

      if (type.IsValueType) { 
       return type.FullName + "?"; 
      } 
      return type.FullName; 
     } 

     public void GenerateForWeb(SPWeb web) { 
      var blackList = new[] { 
       "Documents", "Form Templates", "Site Assets", "Site Pages", "Style Library" 
      }; 

      Directory.CreateDirectory(parentDir); 
      Directory.CreateDirectory(hiddenDir); 

      foreach(SPList list in web.Lists) { 
       PropertyString _classDefinition = new PropertyString(_classDefinitionStr); 

       string entityName = "SPL_" + list.Title.Replace(" ", ""); 
       _classDefinition["EntityName"] = entityName; 

       foreach(SPField field in list.Fields) { 
        PropertyString propertySection = new PropertyString(_propertySectionStr); 

        propertySection["PropertyType"] = GetSafeTypeName(field); //field.FieldValueType.FullName; -> Returning Null often. Thanks, SharePoint! 
        propertySection["PropertyName"] = field.EntityPropertyName.Replace("_x0020_", "_"); 
        propertySection["PropertyId"] = field.Id.ToString(); 

        if (SPBuiltInFieldId.Contains(field.Id)) _classDefinition["InternalPropertySections"] += propertySection; 
        else if (field.Hidden) _classDefinition["HiddenPropertySections"] += propertySection; 
        else _classDefinition["PropertySections"] += propertySection; 
       } 

       if (list.Hidden || blackList.Contains(list.Title)) { 
        File.WriteAllText(hiddenDir + entityName + ".cs", _classDefinition.ToString()); 
       } else { 
        File.WriteAllText(parentDir + entityName + ".cs", _classDefinition.ToString()); 
       } 
      } 



     } 

    } 


} 
-1

你可以使用一個ExpandoObject,這是在System.Dynamic命名空間。嘗試是這樣的(未經測試):

public class SPListItemPropertyMapper 
{ 
    private dynamic _expandoObject; 

    public SPListItemPropertyMapper(SPListItem listItem) 
    { 
     _expandoObject = new ExpandoObject(); 
     foreach (SPField field in listItem.Fields) 
     {    
      _expandoObject.Add(field.InternalName, listItem.GetFormattedValue(field.InternalName)); 
     } 
    } 

    public dynamic FieldValues 
    { 
     get { return _expandoObject; } 
    } 
} 

用法:

SPListItem listItem; //your list item here 
var propertyMapper = new SPListItemPropertyMapper(listItem); 

var title = propertyMapper.FieldValues.Title; 
var editor = propertyMapper.FieldValues.Editor; 
var created = propertyMapper.FieldValues.Created; 

等等。你應該考慮更多的邏輯延伸foreach循環,返回基於字段類型的值,而不是僅僅使用GetFormattedValue

+0

如果你使用'dynamic',那麼你仍然沒有得到任何編譯時類型檢查,所以你只用'SPLIstItem'就沒有任何好處。 – Servy

+0

你說得對。我甚至會用參數來使用LINQ到SharePoint。但至少這是朝着OP想要的方向發展的一種方法。 – LInsoDeTeh

+1

然而它並沒有真正回答問題,它實際上也沒有幫助。 – Servy

0

對於我的前僱主我實現了一個DAO pattern爲SharePoint。不幸的是,我不能把代碼與我或發佈...我用註解連同反射來解決不同的名稱,可選字段,類型轉換等等。我也寫的DTO對象發電機的問題。但說實話,對於LINQ在你的情況下可能解決的問題,這是一個相當大的努力。或者手動編寫你的類,或者爲getter和setter編寫代碼生成器 - 這完全取決於你的項目的大小。

之前實現我自己的DAO我有一個LINQ相當糟糕的經驗,SQL,尤其是當列被重命名,添加或刪除我不喜歡的行爲,我用它也有性能問題。這就是爲什麼我喜歡我自己的DAO模式,但爲了簡單的任務,LINQ可能就足夠了。我與LINQ的經驗也可能已經過期,這是大約7年前;)

+0

這是一個非常有趣的答案!也許我們可以再次實施它? :) – David