将 SharePoint 列表项映射到 C# class

Mapping a SharePoint list item to a C# class

假设我有:

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?

您可以使用 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 循环扩展到基于字段类型的 return 值,而不是仅使用 GetFormattedValue.

我为我的前雇主实施了一个 DAO pattern 的 SharePoint。不幸的是,我不允许随身携带代码或发布它……我使用注释和反射来解决不同名称、可选字段、类型转换等问题。我还为 DTO 对象编写了一个生成器。但老实说,对于 LINQ 在您的案例中可能解决的问题来说,这是一个相当大的努力。或者手动编写 类,或者为 getter 和 setter 编写代码生成器——这完全取决于项目的大小。

在实施我自己的 DAO 之前,我对 LINQ to SQL 的体验非常糟糕,尤其是在重命名、添加或删除列时,我不喜欢这种行为,我在使用它时也遇到了性能问题。这就是为什么我更喜欢我自己的 DAO 模式,但对于简单的任务,LINQ 可能就足够了。我对 LINQ 的体验也可能已经过时了,那是大约 7 年前的事了 ;)

Aaaaa,我们开始吧。 class 从您的列表中生成实体。 来自: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());
                }
            }



        }

    }


}