Сначала вносим некоторые изменения в сам BLToolkit, дабы он генерировал атрибуты DataContract и DataMember.
В класс AbstractClassBuilder, метод DefineNonAbstractType, в самый конец:
if(_context.Type.GetCustomAttributes(typeof (DataContractAttribute)).Length > 0)
_context.TypeBuilder.SetCustomAttribute(typeof(DataContractAttribute));
В класс BuildContext, метод CreateField :
public FieldBuilder CreateField(string fieldName, Type type, FieldAttributes attributes)
{
FieldBuilder field = TypeBuilder.DefineField(fieldName, type, attributes);
field.SetCustomAttribute(MethodBuilder.Type.Assembly.BLToolkitAttribute);
// Это я добавил
if (Type.GetCustomAttributes(typeof(DataContractAttribute)).Length > 0)
{
CustomAttributeBuilder cab = new CustomAttributeBuilder(
typeof(DataMemberAttribute).GetConstructor(new Type[] { }), new object[] { });
field.SetCustomAttribute(cab);
}
// Конец вставки
Items.Add("$BLToolkit.Field." + fieldName, field);
return field;
}
Далее создаем специальный аттрибут:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class BLToolkitKnownTypeAttribute : Attribute, IOperationBehavior
{
private Type knownType;
public BLToolkitKnownTypeAttribute(Type type)
{
object obj = TypeAccessor.CreateInstanceEx(type);
knownType = obj.GetType();
}
public void Validate(OperationDescription operationDescription)
{
if(!operationDescription.KnownTypes.Contains(knownType))
operationDescription.KnownTypes.Add(knownType);
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void AddBindingParameters(OperationDescription operationDescription,
BindingParameterCollection bindingParameters)
{
}
}
Пример:
DataContract:
[DataContract]
public abstract class Principal
{
public abstract long ID { get; set;}
public abstract string Name { get; set; }
public abstract bool IsGroup { get; set; }
public abstract bool Disabled { get; set; }
}
ServiceContract:
[ServiceContract]
public interface IUserRightsManager
{
[OperationContract]
[BLToolkitKnownType(typeof(Principal))]
List<Principal> GetAllPrincipal();
[OperationContract]
[BLToolkitKnownType(typeof(Principal))]
void ChangeDisablePricipal(Principal principal);
}
Все. DataContract'ы ходят. Копировать библиотеки на клиент
не надо.
Может стоит еще потестировать и включить решение в основной код?
Здравствуйте, Shadowspan, Вы писали:
S>В класс AbstractClassBuilder, метод DefineNonAbstractType, в самый конец:
S>S> if(_context.Type.GetCustomAttributes(typeof (DataContractAttribute)).Length > 0)
S> _context.TypeBuilder.SetCustomAttribute(typeof(DataContractAttribute));
S>
Этот момент (и следующий) нужно обобщить. Можно реализовать что-то вроде
[BLToolkitExtensionAttribute(typeof(DataContractAttribute))]]
public abstract class Principal
{
public abstract long ID { get; set;}
public abstract string Name { get; set; }
public abstract bool IsGroup { get; set; }
[BLToolkitExtensionAttribute(typeof(SomeOtherAttribute), arg1, arg2)]]
public abstract bool Disabled { get; set; }
}
т.е. научить AbstractClassBuilder добавлять
какие-то аттрибуты прямо в генерируемые методы и свойства.
Можно сделать иначе. Например, завести у TypeBuilder'а соллекцию типов аттрибутов, которые он будет всегда копировать в атрибуты генерируемых мемберов.
Как-то так:
[DataContract]
public abstract class Principal
{
public abstract long ID { get; set;}
public abstract string Name { get; set; }
public abstract bool IsGroup { get; set; }
[SomeOther(arg1, arg2)]
public abstract bool Disabled { get; set; }
}
// ..
TypeFactory.DefineTransitAttribute(typeof(DataContractAttribute));
TypeFactory.DefineTransitAttribute(typeof(SomeOtherAttribute));
S>Далее создаем специальный аттрибут:
S>S> public class BLToolkitKnownTypeAttribute : Attribute, IOperationBehavior
S> {
S> private Type knownType;
S> public BLToolkitKnownTypeAttribute(Type type)
S> {
S> object obj = TypeAccessor.CreateInstanceEx(type);
S> knownType = obj.GetType();
S> }
S> }
S>
Это можно (и нужно) сделать проще:
public BLToolkitKnownTypeAttribute(Type type)
{
knownType = TypeAccessor.GetAccessor(type).Type;
}
... << RSDN@Home 1.2.0 alpha rev. 692>>
Здравствуйте, Блудов Павел, Вы писали:
БП>Этот момент (и следующий) нужно обобщить. Можно реализовать что-то вроде
БП>БП>[BLToolkitExtensionAttribute(typeof(DataContractAttribute))]]
БП>public abstract class Principal
БП>{
БП> public abstract long ID { get; set;}
БП> public abstract string Name { get; set; }
БП> public abstract bool IsGroup { get; set; }
БП> [BLToolkitExtensionAttribute(typeof(SomeOtherAttribute), arg1, arg2)]]
БП> public abstract bool Disabled { get; set; }
БП>}
БП>
БП>т.е. научить AbstractClassBuilder добавлять какие-то аттрибуты прямо в генерируемые методы и свойства.
Только BLToolkitExtensionAttribute нужен еще один параметр — Target. Куда ставить этот атрибут — к полю или к свойству или классу. Так как, например атрибут DataMember надо учтановить не у свойства а у поля, генерируемого Framework'ом.
БП>Это можно (и нужно) сделать проще:
БП>БП>public BLToolkitKnownTypeAttribute(Type type)
БП>{
БП> knownType = TypeAccessor.GetAccessor(type).Type;
БП>}
БП>
Спасибо поравил
Здравствуйте, Shadowspan, Вы писали:
S>Только BLToolkitExtensionAttribute нужен еще один параметр — Target. Куда ставить этот атрибут — к полю или к свойству или классу. Так как, например атрибут DataMember надо учтановить не у свойства а у поля, генерируемого Framework'ом.
Можно и без него обойтись. Дело в том, что BLToolkit не создаёт в генерируемом классе свойства — только getter'а и setter'а.
Поэтому любой атрибут, назначенный на свойство будет "виден" в сгенерированном классе.
Следовательно можно
всегда считать, что такой атрибут влияет не на свойство, а на поле, генерируемое для этого свойства.
Забирайте последнюю версию, пример можно посмотреть в
UnitTests\CS\TypeBuilder\GenerateAtributeTest.cs... << RSDN@Home 1.2.0 alpha rev. 692>>