Assembly.LoadFrom получить пользовательский атрибут

Вопрос: используя только Assembly.LoadFrom и имея только имя пользовательского атрибута, как я могу найти, а затем создать экземпляр любого класса с этим именованным пользовательским атрибутом?

Код в DLL:

[AttributeUsage(AttributeTargets.All)]
public class ClassAttribute : Attribute
{
    private string myName;
    public ClassAttribute() { }
    public ClassAttribute(string className) 
    {
        myName = className;
    }
    public string MyName { get { return myName; } }
}

//Edit ... added this after initial post
[AttributeUsage(AttributeTargets.All)]
public class MethodAttribute : Attribute
{
    private string myMethodName;
    public MethodAttribute(){}
    public MethodAttribute(string methodName)
    {
        myMethodName = methodName;
    }
    public string MyMethodName { get { return myMethodName; } }
}

[ClassAttribute("The First Class")]
public class myClass
{
    //Edit ... added this after initial post
    [MethodAttribute("Find this method after finding this class")]
    public string methodOne()
    {
        return "This response from myclass methodOne";
    }

    public string methodTwo()
    {
        return "This response from myClass methodTwo";
    }
}

Код в классе потребления в отдельном решении VS2k12:

Assembly asm = Assembly.LoadFrom(@"C:\References\WebDemoAttributes.dll");

string attributeName = "Find this class using this attribute name";

// используя attributeName, как я могу найти WebDemoAttributes.myClass, создать его экземпляр и затем вызвать methodOne()?

Заранее спасибо и ура!


Это то, что я наконец придумал для всех, кто интересуется поиском классов в DLL по специальному атрибуту:

protected void lb_debugInClassLibrary_Click(object sender, EventArgs e)
{
    LinkButton lb = sender as LinkButton;

    Assembly asm1 = Assembly.Load("WebDemoAttributes");

    var classAttributesTypes = asm1.GetTypes().Where(t => t.GetCustomAttributes()
        .Any(a => a.GetType().Name == "ClassAttribute")).ToList();

    foreach (Type type in classAttributesTypes)
    {               
        Attribute[] attrs = Attribute.GetCustomAttributes(type);               

        foreach (Attribute atr in attrs)
        {
            var classWithCustomAttribute = atr as WebDemoAttributes.ClassAttribute;
            if (classWithCustomAttribute.MyName == "The First Class" 
                && lb.ID.ToString().ToLower().Contains("thefirstclass"))
            {
                var mc = Activator.CreateInstance(type) as WebDemoAttributes.MyClass;
                //TODO figure out how to get the attributes decorating mc's methods
                if (lb.ID.ToString().ToLower().Contains("methodone"))
                    lbl_responseFromMyClass.Text = mc.MethodOne();
                else if (lb.ID.ToString().ToLower().Contains("methodtwo"))
                    lbl_responseFromMyClass.Text = mc.MethodTwo();
            } 
            if (classWithCustomAttribute.MyName == "The Second Class" 
                && lb.ID.ToString().ToLower().Contains("thesecondclass"))
            {
                var yc = Activator.CreateInstance(type) as WebDemoAttributes.YourClass;
                if (lb.ID.ToString().ToLower().Contains("methodone"))
                    lbl_responseFromYourClass.Text = yc.MethodOne();
                else if (lb.ID.ToString().ToLower().Contains("methodtwo"))
                    lbl_responseFromYourClass.Text = yc.MethodTwo();
            }
        }
    }
}

2 ответа

Решение
var asm = Assembly.LoadFrom(@"C:\References\WebDemoAttributes.dll");

var myClassType = asm.GetTypes()
                     .FirstOrDefault(t => t.GetCustomAttributes()
                     .Any(a => a.GetType().Name == "ClassAttribute"));

Ваш вопрос:

используя attributeName, как я могу найти WebDemoAttributes.myClass, создать его экземпляр и затем вызвать methodOne()?

Ответ: не используйте атрибуты. Вместо этого используйте интерфейсы.

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

Они не могут использоваться для обеспечения ограничений дизайна (по крайней мере, не из коробки). Итак, спрашивая, можете ли вы найти данный класс с помощью поиска по атрибутам, а затем вызвать methodOne() для класса, не является действительным вопросом, потому что наличие атрибута в классе не подразумевает существование methodOne,

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

Другие вопросы по тегам