使用BreezeSharp的动态对象

时间:2014-08-12 17:03:56

标签: c# json breeze breeze-sharp

我正在开发一个需要使用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继承的对象,并列出属性。

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

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

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

1 个答案:

答案 0 :(得分: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()
             );
         }
    }
}

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

您现在可以使用

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

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

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

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