2010-06-14 1 views
2

скажем, у меня есть 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 в бар во время выполнения?

+0

Просто убедитесь, что вы имеете в виду значение Name или вы имеете в виду атрибут, украшающий свойство Name? Вы хотите, чтобы Bar.Name был равен Foo.Name или что Bar.Name будет украшено [Обязательно]? – Elisha

+0

@ Elisha Bar.Name будет украшен Обязательным – Omu

ответ

4

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

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

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

8

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

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

2

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

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

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

+0

ну, в основном я просто хочу знать, можно ли украсить атрибуты во время выполнения до или после создания экземпляра какого-то типа – Omu

+1

@Omu: Нет. По крайней мере, без много магии отражения (которая используется, например, различными прокси-серверами, которые автоматически реализуют интерфейсы и т. д.). Но будет ли практическое использование этого? –

+0

, так что это возможно, все, что нам нужно сейчас, это тот, кто знает, как это сделать; практический? ну да, если вам нужно украсить некоторые свойства во время выполнения, чем это поможет ya – Omu

0

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

Похоже здесь http://msdn.microsoft.com/en-us/library/ms171819.aspx

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

3

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

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

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

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

-4

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

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

Binary сайт выпуска: http://automapper.codeplex.com

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

0

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

Bus bus; 
BigVehicle big = bus; 

public static implicit operator Bigvehicle(Bus bus) 
{ 

}