Динамические объекты с BreezeSharp
Я работаю над проектом, который требует работы с динамическими объектами с 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 после создания динамического объекта.
Причина, по которой мне это нужно, заключается в том, что у меня есть приложение SharePoint, которое использует BreezeJS. Сущности основаны на файле JSON.
Поэтому я хочу создать приложение для рабочего стола, которое будет использовать те же объекты на основе файла JSON. Я не уверен, что возможно создавать динамические объекты, которые наследуют класс BaseEntity.
1 ответ
Да, это возможно, но вам нужно немного поработать и написать код. Вот идея (не проверенная):
Создайте класс, который наследует от 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), но должен указывать правильное направление.