0

我正在开发一个需要使用 BreezeSharp 处理动态对象的项目。我通过 JSON 文件接收对象的结构,例如:

[{
    name: 'Admin',
    serviceAddress: 'http://abcd.com/breeze/admins',
    dataProperties: {
    Id: { type: breeze.DataType.Int32 },
    Title: { nullable: true },
    ContentTypeId: {},
    Created: { type: breeze.DataType.DateTime },
    Modified: { type: breeze.DataType.DateTime },
    File: { complexType: 'Document:#File' },
},
{
    name: 'Car',
    serviceAddress: 'http://abcd.com/breeze/cars',
    dataProperties: {
    Id: { type: breeze.DataType.Int32 },
    Model: { nullable: true },
    Created: { type: breeze.DataType.DateTime },
    Modified: { type: breeze.DataType.DateTime },
}]

我想使用列出的属性自动生成从 Breeze.Sharp.BaseEntity 继承的对象。

在创建动态对象后,我还必须创建微风实体管理器。

我需要这个的原因是因为我有一个使用 BreezeJS 的 SharePoint 应用程序。这些实体基于那里的 JSON 文件。

所以我想创建一个桌面应用程序,它将使用基于 JSON 文件的相同实体。我不确定是否可以创建继承 BaseEntity 类的动态对象。

4

1 回答 1

2

是的,这是可能的,但是您需要在其中投入一些工作和代码。这是这个想法(未经测试):

创建一个继承BaseEntity并实现IDynamicMetaObjectProvider的类。然后,您需要构建将函数定义转换为动态属性的函数:

public class DynamicBreezeEntity : BaseEntity, IDynamicMetaObjectProvider
{
    private readonly Dictionary<string, PropertyDefinition> _properties;

    public DynamicBreezeEntity ()
    {
        _properties = new Dictionary<string, PropertyDefinition>();
    }

    public void DefineProperty(string name, Type type, bool isNullable = false)
    {
        if (string.IsNullOrEmpty(name))
            throw new ArgumentNullException("name");

        if (_properties.ContainsKey(name))
            throw new ArgumentException("Property already defined.", "name");

        if (type == null)
            throw new ArgumentNullException("type");

        if (isNullable && !type.IsValueType)
            throw new ArgumentException("Only value types can be nullable.", "type");            

        if (isNullable)
        {
            type = Nullable.GetUnderlyingType(type);
            if (type.IsValueType)
                type = typeof(Nullable<>).MakeGenericType(type);
        }

        _properties.Add(name, new PropertyDefinition { Type = type });
    }

    public object GetValue(string name)
    {
        PropertyDefinition def;
        if (_properties.TryGetValue(name, out def))
            return def.Value;

        throw new ArgumentException("Property not defined.", "name");
    }

    public void SetValue(string name, object value)
    {
        // more work todo here: handle value == null correctly

        PropertyDefinition def;
        if (_properties.TryGetValue(name, out def) && def.Type.IsAssignableFrom(value.GetType()))            
            def.Value = value;

        throw new ArgumentException("Property not defined.", "name");
    }

    public IEnumerable<string> GetPropertyNames()
    {
        return _properties.Keys.ToList();
    }

    DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
    {
        return new Proxy(this);
    }   

    private class PropertyDefinition
    {
        public Type Type { get; set; }

        public object Value { get; set; }
    }

    private class Proxy : DynamicMetaObject 
    {
         public Proxy(DynamicBreezeEntity host, Expression expression)
             : this(host, expression, BindingRestrictions.Empty) { }

         public Proxy(DynamicBreezeEntity host, Expression expression, BindingRestrictions restrictions)
             : base(expressiom restrictions, host) { }

         private DynamicBreezeEntity Host
         {
             get { return (DynamicBreezeEntity)Value; }
         }

         private BindingRestrictions GetBindingRestrictions()
         {
             var restrictions = BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType);
             return restrictions.Merge(BindingRestrictions.GetInstanceRestriction(this.Expression, this.Host));            
         }

         public override IEnumerable<string> GetDynamicMemberNames()
         {
             return this.Host.GetPropertyNames();
         }

         public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
         {
            var arguments = new Expression[] { Expression.Constant(binder.Name) };
            var method = typeof(DynamicBreezeEntity).GetMethod("GetValue");

            var callExpression = Expression.Convert(Expression.Call(Expression.Convert(this.Expressiom, this.LimitType), method, arguments), binder.ReturnType);
            return new DynamicMetaObject(callExpression, GetBindingRestrictions());
         }

         public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
         {
             var arguments = new Expression[] {
                 Expression.Constant(binder.Name),
                 Expression.Convert(value.Expression, typeof(object))
             };
             var method = typeof(DynamicBreezeEntity).GetMethod("SetValue");
             return new DynamicMetaObject(
                 Expression.Call(Expression.Convert(this.Expression, this.LimitType), method, arguments),
                 this.GetBindingRestrictions()
             );
         }
    }
}

我不知道微风,BaseEntity可能有你需要实现的抽象属性/方法。我没有专注于此。

您现在可以用作

var breeze = new DynamicBreezeEntity();
breeze.DefineProperty("Id", typeof(Int32));

dynamic dynBreeze = breeze;
dynBreeze.Id = "Foo";

Console.WriteLine("Id: {0}", dynBreeze.Id);

代码可能不完整(目前没有 VS 访问权限),但应该为您指明正确的方向。

于 2014-08-12T18:53:54.457 回答