KSav
KSav

Reputation: 3

C# how to create class instance by class attributes

How do I create a class instance using known attributes? In this the attributes are values of an enum.

public enum MyEnum
{
    Value1,
    Value2
}

class MyAttribute : Attribute... //attribute definition class
{ //uses the enum}

//Main
abstract class MyMain ... 
{
     public static MyMain CreateClass
     {
        MyMain newInheritedClass = ?
     }
}

[MyAttribute(MyEnum.Value1)]
class MyClassA : MyMain ...

[MyAttribute(MyEnum.Value2)]
class MyClassB : MyMain ...

Upvotes: 0

Views: 1964

Answers (2)

Fabio
Fabio

Reputation: 32445

For the purposes you describe in comments I think using attributes is little bid overkill.
Just create a static method or factory class with method which will do the same things:

public static MyMain CreateInstance(MyEnum attribute)
{
    if(attribute == MyEnum.Value1)
    {
        return new MyClassA();
    }
    else
    {
        //...
    }
}

Of course if you have a task to create instance based on the attributes then:

private readonly Dictionary<MyEnum, Type> _Data;

public Factory(Assembly assembly) 
{
    var myAttributeClasses = 
        assembly.GetTypes()
                .Select(t => new 
                {
                    DirevedType = t,
                    Attribute = (MyAttribute)t.GetCustomAttribute(typeof(MyAttribute))
                })
                .Where(data => data.Attribute != null);

    _Data = new Dictionary<MyEnum, Type>();
    foreach(var data in myAttributeClasses)
    {
        _Data.Add(data.Attribute.EnumValue, data.DerivedType);
    }
}

public MyMain CreateInstance(MyEnum enumvalue)
{
    Type derivedType;
    if(_Data.TryGetValue(enumvalue, out derivedType) == false) 
        return null;

    return Activator.CreateInstance(derivedType);
}

Upvotes: 0

InBetween
InBetween

Reputation: 32740

I competely agree with Fabio's answer in that using attributes seems an overkill here but we don't have enough information to really know why you are using this approach so I'll show you how it would be done:

Your method CreateClass should look like this:

public static MyMain CreateClass(MyEnum value)
{
    var targetType = Assembly.GetExecutingAssembly()
                             .GetTypes()
                             .Where(t => t.IsSubclassOf(typeof(MyMain)) &&
                                    t.GetCustomAttribute<MyAttribute>()?.Value == value)
                             .FirstOrDefault();

    if (targetType != null)
        return Activator.CreateInstance(targetType) as MyMain;

    return null;
}

This presuposes two things:

  1. Your derived classes are defined in the executing assembly.
  2. Your derived classes have public parameterless constructors.

If niether is the case you can still adapt the solution investigating a little.

Upvotes: 2

Related Questions