new() with reflection on FieldType - c#

I have some code that looks like
else if (oField.FieldType.IsClass)
{
//var t = oField.FieldType.new()
someObj.fill_data(t);
oField.SetValue(o, t);
}
I dont know how to allocate var t. How might i do this? There no way for me to know what the type could be so writing FieldType.IsAssignableFrom(KnownType) can not be a workaround.

Try Activator.CreateInstance:
object t = Activator.CreateInstance(oField.FieldType);
This assumes that type FieldType has a default constructor.

Here is some example code:
class TypeTest
{
int m_parameter;
public TypeTest()
{
}
public TypeTest(int parameter)
{
m_parameter = parameter;
}
public int Param { get { return m_parameter; } }
}
//method1 - Using generic CreateInstance
TypeTest defConstructor = Activator.CreateInstance <TypeTest>();
//method2 - Using GetConstructor
ConstructorInfo c = typeof(TypeTest).GetConstructor(new Type[] { typeof(int)});
TypeTest getConstructor = (TypeTest)c.Invoke(new object[] { 6 });
//method3 - Using non-generic CreateInstance
TypeTest nonDefaultConstructor = (TypeTest)Activator.CreateInstance(typeof(TypeTest), 6);

Perhaps you should look into the Type.GetConstructor(...).Invoke(...) of the returned Type.

Related

C# How To Initialize a generic Class with a type variable

disclaimer I'm a newbie in understanding Reflection.
abstract class BaseClass<T>
{
public abstract T Value { get; }
public virtual bool CheckValue(string input)
{
return true;
}
}
class NotBaseClassA : BaseClass<string>
{
public override string Value { get => "Yes";}
public override bool CheckValue(string input)
{
return 1 == 2;
}
}
class NotBaseClassB : BaseClass<int>
{
public override int Value { get => 1; }
}
class ManyBaseClasses
{
public NotBaseClassB notBaseClassB;
public NotBaseClassA notBaseClassA;
}
class Programm
{
public void Main()
{
foreach (PropertyInfo pi in typeof(ManyBaseClasses).GetProperties())
{
string input = Console.ReadLine();
//Get the generic type of the propertyInfo
//BaseClass<type> bt = new BaseClass<type>();
//Instantiate BaseClass not as a var So I can do
//BaseClass.CheckValue(input)
}
}
}
I'm just trying to do like the title says. So i saw this answer but the answer returns a 'var' but I cant call my CheckValue() function from a type var. (Or i dont think I can?). What i Need is to Instantiate my BaseClass<> with the correct type from a type variable and not as a var, as a proper BaseClass obj so i can then call my functions.
Edit 1 : i've already managed to get the generic type in the variable by doing something like that
public static System.Type GetBaseClassType(this System.Type type)
{
System.Type[] types = new System.Type[]{ };
while (type != null && type != typeof(object) || types.Length == 0)
{
types = type.GetGenericArguments();
if (types.Length > 0)
{
return types[0];
}
type = type.BaseType;
}
return null;
}
The base class is not relevant in this case, as it's abstract, so you actually want to instantiate the derived class.
All you need to do to create it is
Activator.CreateInstance(pi.PropertyType)
Then you will need to use reflection on that result to call CheckValue, because there is no common base type or interface.
It might be easier to extract the non-generic code into a BaseBaseClass which is not generic, which means you don't need reflection for the second step.
abstract class BaseBaseClass
{
public virtual bool CheckValue(string input)
{
return true;
}
}
abstract class BaseClass<T> : BaseBaseClass
{
public abstract T Value { get; }
}
Then you can just do
((BaseBaseClass) Activator.CreateInstance(pi.PropertyType)).CheckValue(someInput)
I've done that before, but it was a long time ago. You have to create instance via reflection and call the method via reflection.
foreach (PropertyInfo pi in typeof(ManyBaseClasses).GetProperties())
{
string input = Console.ReadLine();
//Get the generic type of the propertyInfo
var propType = pi.Type;
Type[] typeArgs = { propType };
var genType = d1.MakeGenericType(typeArgs);
//BaseClass<type> bt = new BaseClass<type>();
object bt = Activator.CreateInstance(genType);
//Instantiate BaseClass not as a var So I can do
//BaseClass.CheckValue(input)
MethodInfo method = typeof(bt).GetMethod("CheckValue"));
method.Invoke(bt, new[] { input });
}

Unable to cast object of type System.RuntimeType to System.Enum [duplicate]

I'm in a situation where I'd like to instantiate an object of a type that will be determined at runtime. I also need to perform an explicit cast to that type.
Something like this:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
structType myStruct = (structType)Marshal.PtrToStructure(IntPtr, structType);
}
This is obviously not valid code, but I hope it conveys the essence of what I'm trying to do. The method I'm actually working on will have to perform the marshaling operation on ~35 different types. I have several other methods that will need to do something similar with the same set of types. So, I'd like to isolate the type-determining logic from these methods so that I only need to write it once, and so that the methods stay clean and readable.
I must admit to being a total novice at design. Could anyone suggest a good approach to this problem? I suspect there might be an appropriate design pattern that I'm unaware of.
There are several ways you can create an object of a certain type on the fly, one is:
// determine type here
var type = typeof(MyClass);
// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);
And you'll get an instance of MyClass in obj.
Another way is to use reflection:
// get type information
var type = typeof(MyClass);
// get public constructors
var ctors = type.GetConstructors(BindingFlags.Public);
// invoke the first public constructor with no parameters.
var obj = ctors[0].Invoke(new object[] { });
And from one of ConstructorInfo returned, you can "Invoke()" it with arguments and get back an instance of the class as if you've used a "new" operator.
You can mostly do what you're describing, but since you don't know the type at compile-time, you'll have to keep the instance loosely-typed; check its type at each point you use it, and cast it appropriately then (this will not be necessary with c# 4.0, which supports dynamics):
Type type = CustomGetTypeMethod();
var obj = Activator.CreateInstance(type);
...
if(obj is MyCustomType)
{
((MyCustomType)obj).Property1;
}
else if (obj is MyOtherCustomType)
{
((MyOtherCustomType)obj).Property2;
}
I think you're looking for Activator.CreateInstance
Creating an instance of a run-time determined Type is easy, using Activator.CreateInstance, as others have mentioned. However, casting it, as you do in your example on the Marshal.PtrToStructure line is not possible, as the type has to be known at compile time for casting. Also, note that Activator.CreateInstance can not be used in conjunction with an IntPtr.
If your types have a common base class (other than Object), you can cast it to said base type and call functions on that. Otherwise, calling functions will only be possible using reflection.
So either:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr val = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
BaseClass myStruct = (BaseClass)Marshal.PtrToStructure(IntPtr, structType);
myStruct.SomeFunctionDeclaredInBaseClass();
}
Or:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr val = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
object myStruct = Marshal.PtrToStructure(IntPtr, structType);
MemberInfo[] function = FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
(MemberFilter)delegate(MemberInfo info, object filter)
{
return info.Name == filter.ToString();
}, "SomeFunction");
if (mi.Length > 0 && mi[0] is MethodInfo)
((MethodInfo)mi[0]).Invoke(myStruct, ..params..);
}
You could go dynamic:
using System;
namespace TypeCaster
{
class Program
{
internal static void Main(string[] args)
{
Parent p = new Parent() { name = "I am the parent", type = "TypeCaster.ChildA" };
dynamic a = Convert.ChangeType(new ChildA(p.name), Type.GetType(p.type));
Console.WriteLine(a.Name);
p.type = "TypeCaster.ChildB";
dynamic b = Convert.ChangeType(new ChildB(p.name), Type.GetType(p.type));
Console.WriteLine(b.Name);
}
}
internal class Parent
{
internal string type { get; set; }
internal string name { get; set; }
internal Parent() { }
}
internal class ChildA : Parent
{
internal ChildA(string name)
{
base.name = name + " in A";
}
public string Name
{
get { return base.name; }
}
}
internal class ChildB : Parent
{
internal ChildB(string name)
{
base.name = name + " in B";
}
public string Name
{
get { return base.name; }
}
}
}
methodName = NwSheet.Cells[rCnt1, cCnt1 - 2].Value2;
Type nameSpace=typeof(ReadExcel);
Type metdType = Type.GetType(nameSpace.Namespace + "." + methodName);
//ConstructorInfo magicConstructor = metdType.GetConstructor(Type.EmptyTypes);
//object magicClassObject = magicConstructor.Invoke(new object[] { });
object magicClassObject = Activator.CreateInstance(metdType);
MethodInfo mthInfo = metdType.GetMethod("fn_"+methodName);
StaticVariable.dtReadData.Clear();
for (iCnt = cCnt1 + 4; iCnt <= ShtRange.Columns.Count; iCnt++)
{
temp = NwSheet.Cells[1, iCnt].Value2;
StaticVariable.dtReadData.Add(temp.Trim(), Convert.ToString(NwSheet.Cells[rCnt1, iCnt].Value2));
}
//if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_AddNum" || Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_SubNum")
//{
// //StaticVariable.intParam1 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 4].Value2);
// //StaticVariable.intParam2 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 5].Value2);
// object[] mParam1 = new object[] { Convert.ToInt32(StaticVariable.dtReadData["InParam1"]), Convert.ToInt32(StaticVariable.dtReadData["InParam2"]) };
// object result = mthInfo.Invoke(this, mParam1);
// StaticVariable.intOutParam1 = Convert.ToInt32(result);
// NwSheet.Cells[rCnt1, cCnt1 + 2].Value2 = Convert.ToString(StaticVariable.intOutParam1) != "" ? Convert.ToString(StaticVariable.intOutParam1) : String.Empty;
//}
//else
//{
object[] mParam = new object[] { };
mthInfo.Invoke(magicClassObject, mParam);

Generics - using GetRuntimeMethod with type parameter

Trying to write a utilty method which determines whether a type is parseable (i.e. has a method like: Parse(string value)
The code below works, but seems a bit kludgey:
public static bool IsParseable(Type t) {
string s = "foo";
Type[] typeArray = { s.GetType() };
if (t.GetRuntimeMethod("Parse", typeArray )==null) {
return false;
} else {
return true;
}
}
It seems like there should be a better way to get my hands on String type then having to create an instance of the type (string) in order to call GetType()
This likewise comes up trying to use the method, as in:
bool results = IsParseable(Double); //doesn't compile.
Instead to find out if double is parseable, I have to do something like.
Double v = 1.0;
Type doubleType = v.GetType();
bool result = IsParseable(doubleType);
Is there a more efficient way? Ultimately I want to use this with generic types, where I have a type parameter T and I want to find out if T has a Parse(String value) method:
IsParseable(T)
which of course doesn't work either. And creating an instance of T isn't a great solution because not known if T has a default constructor.
You can use generic approach
public static bool IsParseable<T>()
{
var argumentTypes = new[] { typeof(string) };
var type = typeof(T);
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
// Use it
if (IsParseable<decimal>())
{
// Parse...
}
Or use your approach with Thomas Weller's hint and make method an extension method for Type (even better from readability point of view (opinion based)).
public static bool IsParseable(this Type type)
{
var argumentTypes = new[] { typeof(string) };
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
Then use
if (typeof(decimal).IsParseable())
{
// Do something
}

Generic enum as method parameter

Given a constructor
public MyObject(int id){
ID = id;
}
And two enums:
public enum MyEnum1{
Something = 1,
Anotherthing = 2
}
public enum MyEnum2{
Dodo = 1,
Moustache= 2
}
Is it possible to pass in a generic enum as a parameter of the constructor? I'm looking for a solution along the lines of:
public MyObject(enum someEnum){
ID = (int)someEnum;
}
So you can do:
var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);
Another option would be:
public MyObject(Enum someEnum){
ID = Convert.ToInt32(someEnum);
}
This way you can use it like you requested without having to cast to int each time you call your contstructors:
var newObject = new MyObject(MyEnum1.Something);
var anotherObject = new MyObject(MyEnum2.Dodo);
Why do you want to pass the enums, while you could pass integers ?
var newObject = new MyObject((int)MyEnum1.Something);
var anotherObject = new MyObject((int)MyEnum2.Dodo);
and use your first constructor :
public MyObject(int id){
ID = id;
}
Just use a generic constructor:
class MyObject<T> {
public MyObject(T someEnum) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new ArgumentException("Not an enum");
ID = Convert.ToInt32(someEnum);
}
}
Now you can easily call it like this:
var m = new MyObject<MyEnum>(MyEnum1.Something);
But easier would be to pass the enum as integer to the constructor as mentioned in other answers.
EDIT: As of C# 7.3 you can use an enum-constraint right away:
class MyObject<T> where T: Enum { ... }
Well, if you really need to make this call generic for a wide variety of types, then IMHO you should use:
Type.IsEnum to check if your argument is really an Enum;
Enum.GetUnderlyingType to know what type is your argument is based on (it's not necessarily an Int32);
Now cast your object.
public static Int32 GetAnInt<T>(T arg) where T : struct
{
if ((typeof(T).IsEnum))
{
var underlyingType = typeof(T).GetEnumUnderlyingType();
if (underlyingType == typeof(Int32)
|| underlyingType == typeof(Int16)) //etc.
{
try
{
dynamic value = arg;
var result = (Int32)value; // can throw InvalidCast!
return result;
}
catch
{
throw;
}
}
else
{
throw new InvalidCastException("Underlying type
is certainly not castable to Int32!");
}
}
else
{
throw new InvalidCastException("Not an Enum!");
}
}
That way you achieve the beautiful syntax of: var j = GetAnInt(MyEnum.FirstValue);
Are you using properties enum or parameters.
public enum Enum1{}
public Enum1 enum1 { get;set; }
public MyObject()
{
ID = (int)enum1;
}
Just try it. I hope it is useful.

Is there a way to invoke a templated class on an anonymous type?

Here's some code to give the idea.
public class C<T> { }
public class X {
void M() {
var V = new { W = 1 };
var X = new C<V>(); // illegal
}
}
So V is a variable of an anonymous type and I would like to instantiate class C with V as its argument. This requires a type argument, which I cannot supply.
This questions is similar but the answer is not much help in my case: Why can't I instantiate a generic class inferring types from anonymous objects?
The question behind the question is that I'm trying to do what IEnumerable can do.
Should have made it clear: I would really prefer not to do this by manipulating object or Type because you lose the benefits of strong typing and Intellisense.
For anyone interested, the project that needs this is described here: http://www.andl.org/2016/07/andl-net-making-progress/.
You can use type inference if you have a factory method:
public class C<T>
{
public C(T t)
{
// ...
}
}
public static class Factory
{
public static C<T> Create<T>(T t)
{
return new C<T>(t);
}
}
public class Thing
{
void Foo()
{
var x = new { y = "z" };
//var thing = new C(x); - doesn't work, you need to specify the generic parameter
var thing = Factory.Create(x); // T is inferred here
}
}
You can't do that since V is instance of anonymous type, not a type name itself.
You can create this type dynamically (assuming parameterless constructor in C<>):
var X = typeof (C<>)
.MakeGenericType(V.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(new object[0]);
You need a type, you can use pass object as a type.
Sample code:
public class C<T>
{
public T _t { get; set; }
public C(T t)
{
_t = t;
}
public void TestMethod()
{
Console.WriteLine(_t.ToString());
}
}
public class X
{
public void M()
{
var V = new { W = 1 };
var X = new C<object>(V); // everything is an object.
X.TestMethod();
}
}

Categories

Resources