Reputation: 35
i have the class:
public enum ProviderType { SqlClient, OracleClient};
public class ExternalClass
{
private string field1;
private string field2;
private string EnumsDependance;
public ExternalClass(string p1, string p2, ProviderType type)
{
this.field1 = p1;
this.field2 = p2;
if (type == ProviderType.SqlClient)
{
this.EnumsDependance = "SQL TYPE";
}
else if (type == ProviderType.OracleClient)
{
this.EnumsDependance = "ORACLE TYPE";
}
else
{
this.EnumsDependance = "NO TYPE";
}
}
}
In my program I need to create an instance of this class using reflection, but must pass the constructor of this class the value of the enum, how should I do this?
The program is in a different project ExternalClass and ProviderType, and it must be read by reflection. Here is my sketch:
class Program
{
static void Main(string[] args)
{
//dynamically load assembly from file ExternalDLL.dll
Assembly assembly = Assembly.LoadFile(@"C:\temp\ExternalDLL.dll");
//get type of class ProviderType (enum) from just loaded assembly
Type providerType = assembly.GetType("ExternalDLL.ProviderType");
//get type of class ExternalClass from just loaded assembly
Type externalClassType = assembly.GetType("ExternalDLL.ExternalClass");
//creating an instance of the class ExternalClass, using reflection
//constructor -> ExternalClass(string p1, string p2, ProviderType type)
object externalClassInstance = Activator.CreateInstance(externalClassType, new object[]{"param1",
"param2",
"ENUM VALUE" //how should I pass the value?
});
}
}
Upvotes: 2
Views: 3571
Reputation: 3212
The solution
If you have an enum's Type
and want to create it's instance from it's name, do so by using Enum.Parse
. Then you can create your external class instance like this:
object enumInstance = Enum.Parse(providerType, "SqlClient");
object externalClassInstance = Activator.CreateInstance(externalClassType, new object[]{"param1", "param2", enumInstance });
If you want to create an enum's instance from it's value, you can do so by using Enum.ToObject
, like this:
object enumInstance = Enum.ToObject(providerType, 0);
object externalClassInstance = Activator.CreateInstance(externalClassType, new object[]{"param1", "param2", enumInstance });
Why can't I just pass an integer?
There seems to be some confusion why using Enum.ToObject
is necessary. This is because an Enum
is not an Int32
, nor does it inherit from it (it couldn't - all structs in .NET are sealed
). The confusion comes from the fact that you can cast an integer to a specific enum, and get it's instance:
ProviderType enumInstance = (ProviderType)0; // Works just fine
This works because all enums have an explicit cast operator from Int32
. When you do so, internally the enum calls Enum.ToObject
. When you call Activator.CreateInstance
, it does not try to perform a cast or conversion, and tries to use the integer value as a parameter to the constructor. And since the class being created doesn't contain a constructor which takes an int
, you get a MissingMethodException
.
Also, enums don't even have to be int
based, they can be a byte
, sbyte
, short
, ushort
, int
(default), uint
, long
, or ulong
. You can read more about it here.
Upvotes: 3
Reputation: 3102
By value
In C# all enumerations have an underlying type, by default this will be Int32
. You can get the underlying type of the enumeration by calling Type.GetEnumUnderlyingType
.
When no value has been explicitly defined for enumeration values, they will be assigned sequentially, so in your case, SqlClient
will be 0 and OracleClient
will be 1.
You can convert a value of the underlying type to the enumeration type using Enum.ToObject
.
object oracleClient = Enum.ToObject(providerType, 1);
object inst = Activator.CreateInstance(externalClassType, new object[] { "param1", "param2", oracleClient });
By name
Alternatively, you could use Enum.Parse
to get the value by the enumeration value name.
Upvotes: 0