скопировать атрибут свойства из одного экземпляра в другой экземпляр (другого типа) во время выполнения - PullRequest
2 голосов
/ 14 июня 2010

скажем, у меня есть 2 класса, как это:

public class Foo
{
[Required]
public string Name {get;set;}
}

public class Bar 
{
// put here [Required] at run-time
public string Name {get;set;}
}

var foo = new Foo();
var bar = new Bar();
//copy the required from foo to bar

возможно ли скопировать атрибуты из foo в bar во время выполнения?

Ответы [ 7 ]

8 голосов
/ 14 июня 2010

Атрибуты не привязаны к экземплярам - они прикреплены к определениям типов.

Хотя вы можете создавать новые типы во время выполнения с помощью отражения, вы не можете изменять существующие определения типов.

4 голосов
/ 18 июня 2010

Понятие "копирование" атрибутов отсутствует. Тем не менее, вы можете сделать что-то значимое в коде, который проверяет, применяется ли атрибут. Вы можете использовать другой атрибут, который сообщает коду, что он должен использовать другой тип для проверки атрибута [Required]. Например:

[AttributeUsage(AttributeTargets.Class)]
public class AttributeProviderAttribute : Attribute {
    public AttributeProviderAttribute(Type t) { Type = t; }
    public Type Type { get; set; }
}

Что бы вы использовали, как это:

public class Foo {
    [Required]
    public string Name { get; set; }
}

[AttributeProvider(typeof(Foo))]
public class Bar {
    public string Name { get; set; }
}

Код, который проверяет атрибут, может выглядеть так:

    static bool IsRequiredProperty(Type t, string name) {
        PropertyInfo pi = t.GetProperty(name);
        if (pi == null) throw new ArgumentException();
        // First check if present on property as-is
        if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).Length > 0) return true;
        // Then check if it is "inherited" from another type
        var prov = t.GetCustomAttributes(typeof(AttributeProviderAttribute), false);
        if (prov.Length > 0) {
            t = (prov[0] as AttributeProviderAttribute).Type;
            return IsRequiredProperty(t, name);
        }
        return false;
    }

Обратите внимание, как этот код позволяет связывать поставщика атрибутов.

3 голосов
/ 18 июня 2010

Возможно ли это, зависит от того, какие библиотеки должны видеть атрибут. Если код, который должен видеть это, использует отражение , то вы scuppered. Вы не можете сделать это.

Тем не менее, если код, который нуждается в этом, использует компонентную модель, он возможен - но это лот работы. Вы можете реализовать TypeDescriptionProvider, который создает для каждого экземпляра ICustomTypeDescriptor и определяет пользовательские цепочки PropertyDescriptor экземпляров. Затем вы добавите (или замените) атрибуты для каждого свойства, передав их в базовый конструктор (или переопределите свойство атрибутов). В результате ваш атрибут будет содержать следующее:

var attribs = TypeDescriptor.GetProperties(obj)["Name"].Attributes;

Такие вещи, как привязка данных winforms, используют этот API, но он не будет особо заботиться о ваших пользовательских атрибутах. Вы извините меня за то, что я не пишу полный пример, но это много работы; Ни один из этих интерфейсов / базовых типов не является тривиальным для реализации. В конце концов, я сомневаюсь, что оно того стоит.

2 голосов
/ 14 июня 2010

Атрибуты являются частью метаданных сборки (скомпилированной и загруженной), поэтому я не думаю, что вы могли бы легко изменить их во время выполнения.

Единственный вариант, который я могу придумать, - это генерировать код с атрибутом с использованием CodeDOM и перекомпилировать его (и перезагружать сборку), или делать то же самое с помощью System.Reflection.Emit (что было бы возможно, но очень сложно ).

Почему ты хочешь это сделать? Возможно, есть более простой способ решить вашу проблему ...

0 голосов
/ 16 августа 2010

Я здесь упускаю суть? Вы не используете неявный оператор?

Bus bus;
BigVehicle big = bus;

public static implicit operator Bigvehicle(Bus bus)
{

}
0 голосов
/ 23 июня 2010

Пожалуйста, посмотрите на AutoMapper. AutoMapper - это среда отображения, которая может преобразовывать объекты DTO в объекты модели домена.

Введение информации: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx

Сайт бинарных выпусков: http://automapper.codeplex.com

Исходный код релиза сайта: http://code.google.com/p/automapperhome/

0 голосов
/ 17 июня 2010

Если вам нужны атрибуты для выполнения привязки данных или другой задачи, связанной с пользовательским интерфейсом, вы можете попытаться изменить поведение TypeDescriptor по умолчанию.

выглядит здесь http://msdn.microsoft.com/en-us/library/ms171819.aspx

Вы можете добавить свой собственный дескриптор типа для типа, и он позволяет вам предоставлять пользовательские атрибуты для некоторых компонентов, которые используют члены TypeDescriptor.GetXXX вместо непосредственной работы с метаданными типа.

...