I am attempting to take a JSON file that contains data about a generic class (assembly, class name, type parameter names), and dynamically load and instantiate the specified class. I can do this if I use interfaces for the type parameter. However, implementation specifics won't allow me to go this route, so I need to use the specific type parameter classes.
I have the following code so far:
var ci = Invoke.GetClassRef(@"D:\ROCT\Debug\x64 Core\Common Complex Functions.dll", "Namespace.Class");
Type[] typeArgs = { typeof(DoubleABCAry), typeof(FloatABCAry), typeof(Search3Range), typeof(object) };
var _model = ci.GetType().MakeGenericType(typeArgs);
var model = Activator.CreateInstance(_model) as ComplexBaseModel<IModelInput, IModelIOBase, ISearchDimension, object>;
model.Validate();
Line 1: loads the assembly and class. No problem there.
Line 2: lists the types that I need to specify name-wise via a string[]
.
Line 4: DoubleABCAry
implements IModelInput
; FloatABCAry
implements IModelIOBase
, etc.
Line 4 is casting the object to its base definition (shown), which is not what I want. I want RGB255ToCIELAB : ComplexBaseModel<DoubleABCAry, FloatABCAry, Search3Range, object>
.
Line 5 shows that the class is correctly understood. However, the class clearly is implementing interfaces, not the specific types I need.
Is there a way to achieve these two objectives:
model
strongly typed as explained?I know it's achievable with dynamically compiled code, but that is my last resort.
I am using C# 9 preview.
So i think ultimately your problem boils down to the fact that you want to load dynamic
types but then treat them as static
such that you can invoke methods using instance.MyMethod()
syntax. This is not possible (AFAIC) simply because instance.MyMethod()
is compiled down to IL and at that point compiler does not know what instance
is.
So provided you do not have any way of knowing what is the method you want to invoke, you have to go full dynamic route, i.e. use reflection APIs to invoke the right method.
So you would need to supply not just class name but also method name or have a convention e.g. always invoke method called 'Validate'
or something similar.
A simple listing below illustrates my point:
using System;
using System.Reflection;
namespace Shoes {
public interface IA { }
public class A : IA {}
public interface IB { }
public class B : IB {}
public class SomeKindOfModel<T1, T2> {
}
public class ConcreteModel<T1, T2> : SomeKindOfModel<T1, T2> {
public bool Validate() {
return true;
}
}
public class Program
{
public static void Main()
{
// since i don't have your Invoke.GetClassRef, i just did this, works in .net core
var type = Type.GetType($"Shoes.ConcreteModel`2");
var genType = type.MakeGenericType(new[] { typeof(A), typeof(B) });
var instance = Activator.CreateInstance(genType);
var result = genType.GetMethod("Validate", BindingFlags.Instance | BindingFlags.Public)
.Invoke(instance, null); // instead of null you can pass data etc.
Console.WriteLine(result); // prints True
}
}
}