WCF и BLToolkit. Как мне удалось их скрестить.
От: Shadowspan Россия  
Дата: 30.07.07 12:41
Оценка: 34 (3)
Сначала вносим некоторые изменения в сам 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'ы ходят. Копировать библиотеки на клиент не надо.

Может стоит еще потестировать и включить решение в основной код?
Re: WCF и BLToolkit. Как мне удалось их скрестить.
От: Блудов Павел Россия  
Дата: 31.07.07 01:21
Оценка:
Здравствуйте, 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>>
Re[2]: WCF и BLToolkit. Как мне удалось их скрестить.
От: Shadowspan Россия  
Дата: 31.07.07 07:12
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>Этот момент (и следующий) нужно обобщить. Можно реализовать что-то вроде

БП>
БП>[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;
БП>}
БП>


Спасибо поравил
Done
От: Блудов Павел Россия  
Дата: 09.08.07 02:51
Оценка:
Здравствуйте, Shadowspan, Вы писали:

S>Только BLToolkitExtensionAttribute нужен еще один параметр — Target. Куда ставить этот атрибут — к полю или к свойству или классу. Так как, например атрибут DataMember надо учтановить не у свойства а у поля, генерируемого Framework'ом.


Можно и без него обойтись. Дело в том, что BLToolkit не создаёт в генерируемом классе свойства — только getter'а и setter'а.
Поэтому любой атрибут, назначенный на свойство будет "виден" в сгенерированном классе.
Следовательно можно всегда считать, что такой атрибут влияет не на свойство, а на поле, генерируемое для этого свойства.

Забирайте последнюю версию, пример можно посмотреть в UnitTests\CS\TypeBuilder\GenerateAtributeTest.cs
... << RSDN@Home 1.2.0 alpha rev. 692>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.