-2

Question: using only Assembly.LoadFrom and having only the name of a custom attribute how can I find and then instantiate any classes with that named custom attribute?

Code in 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";
    }
}

Code in consuming class in separate VS2k12 solution:

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

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

//using attributeName how can I find WebDemoAttributes.myClass, instantiate it, and then call methodOne()?

Thank you in advance and cheers!


This is what I finally came up with for anyone interested in searching for classes in a DLL by custom attribute:

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();
            }
        }
    }
}
FoolongC
  • 25
  • 3

2 Answers2

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

var myClassType = asm.GetTypes()
                     .FirstOrDefault(t => t.GetCustomAttributes()
                     .Any(a => a.GetType().Name == "ClassAttribute"));
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • The premise is that I have no knowledge of the assembly other than the name and location of the DLL and the name of the attribute to look for. I would have to have a reference to the DLL in the project in order to use 'ClassAttribute'. Was wondering if there's a way to do this without adding a reference to the DLL. – FoolongC Jan 25 '14 at 16:02
  • @FoolongC I noticed that just now.Now I update my answer check again – Selman Genç Jan 25 '14 at 16:03
  • Almost there I think. I drilled into myClassType and this is what I found: {Name = "myClass" FullName = "WebDemoAttributes.myClass"} System.Type {System.RuntimeType} How do I turn myClassType into an instance of myClass so that I can execute its methodOne? – FoolongC Jan 25 '14 at 17:13
  • Also ... I modified your code (for reference if someone else comes here) just a bit to get all types with a certain custom attribute: var myClassType1 = asm.GetTypes().Where(t => t.GetCustomAttributes() .Any(a => a.GetType().Name == "ClassAttribute")); – FoolongC Jan 25 '14 at 17:16
  • @FoolongC take a look at [Activator.CreateInstance](http://msdn.microsoft.com/en-us/library/wccyzw83(v=vs.110).aspx) method – Selman Genç Jan 26 '14 at 03:52
  • Thank you Selman22. I added the final iteration to the original posted code (I settled for adding a reference to the DLL - couldn't figure out any other way). – FoolongC Jan 26 '14 at 12:47
  • You couldn't figure out another way because what you are trying to do does not make sense. – theMayer Jan 27 '14 at 11:32
  • rmayer: Of course it makes no sense; to you. I understand that referencing the DLL gives me the class I'm looking for. Hence no need for an attribute. I was merely trying to see if I could use custom attributes without referencing the DLL. It's called decoupling. Just make the consuming class aware of an attribute name (perhaps in a config file) without making the consumer aware of my implementation. I have this feeling you are one of those devs who simply must be right about everything. I can't stand working with guys like you. They're a pox on team unity. Please go away. – FoolongC Jan 29 '14 at 04:07
0

Your question:

using attributeName how can I find WebDemoAttributes.myClass, instantiate it, and then call methodOne()?

The answer: Don't use attributes. Use interfaces instead.

Attributes are used to set compile-time properties associated with classes that are accessible via reflection. They can be used to mark classes, methods, and assemblies, such that you can search for those specific items based on the existence of the attribute.

They cannot be used to enforce design constraints (at least, not out of the box). So, asking if you can locate a given class via attribute search, and then invoke methodOne() on the class, is not a valid question, because the existence of the attribute on the class does not imply the existence of methodOne.

Instead, I would suggest the use of an interface. You can find all classes that implement an interface, and invoke the method using reflection. This post gives a simple overview of that.

Community
  • 1
  • 1
theMayer
  • 15,456
  • 7
  • 58
  • 90
  • Modified the original posted code and added an attribute for methodOne as well. The assumption is that all I have is the DLL and the name of the attribute ... I don't have a reference to the DLL within the consuming solution so I have no knowledge of any classes or interfaces. I'm thinking I would have to add a reference to the DLL in order to use the classes and interfaces contained therein? – FoolongC Jan 25 '14 at 15:59
  • Your interface would be declared in the main assembly (I assume this is some type of plugin)? Otherwise, you will end up doing something that has no type safety. Which is maybe what you are trying to do? I'm very confused now. – theMayer Jan 25 '14 at 16:19
  • Let's say my company has a 'main' framework team of devs and then several 'sub' teams who use the 'main' framework. Let's also say the 'main' framework team obfuscates their DLLs so there's no way any of the 'sub' teams could get into what they build and thereby decrease the job security of the 'main' framework team. Let's also stipulate that this 'main' framework functionality is accessible via web service only. It would be a huge feather in the cap of a dev who could figure out a way to reduce network hops via web service calls by finding out a way to do what I'm trying to do here. – FoolongC Jan 25 '14 at 17:27
  • If the dll is obfuscated, by definition the names don't make sense. How are you going to search for something by using a known attribute in that case? – theMayer Jan 27 '14 at 11:34
  • I'm going to jump right on that and try and found out. Please wait right here until I get back to you. – FoolongC Jan 29 '14 at 04:12