目录
3.4-《C# 动态创建实例化泛型对象,实例化新对象 new()》
3.6-《MethodInfo.MakeGenericMethod(Type[]) 方法》
3.7-《Type.MakeGenericType(Type[]) 方法》
序言
在C#中,某些场景下,需要根据类的完全限定字符串(就是类名的字符串),动态的实例化对象。
这里最为复杂的,就是根据类名字符串来实例化泛型类与其中的泛型方法了。
下面由简入繁,逐一展示一下如何实现。总体而言,还是使用反射技术,先生成类实例,再调用方法。
注意:只是使用泛型类已定义泛型(如泛型T、泛型R)的方法,不能称为泛型方法,需要有自己的泛型(如泛型U)才能叫泛型方法。
一、先定义两个模型
//普通类
internal class MyClass
{
public string Name { get; set; } = string.Empty;
public string Mes { get; set; } = string.Empty;
public MyClass()
{ }
public MyClass(string name, string mes)
{
Name = name;
Mes = mes;
}
public void MyMethod(IProgress<string> progress)
{
if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Mes))
{
progress?.Report("你调用的是普通类中的普通方法,该类构造函数无参。");
}
else
{
progress?.Report($"你调用的是普通类中的普通方法,该类构造函数有参,Name={Name}");
}
}
public void MyMethodTR<T, R>(IProgress<string> progress)
{
progress?.Report($"调用普通类中的泛型方法,泛型T名称:{typeof(T)},泛型R名称:{typeof(R)}。");
}
}
//泛型类
internal class MyClass<T, R>
where T : class
where R : class
{
public string Name { get; set; } = string.Empty;
public string Mes { get; set; } = string.Empty;
public string TName { get; set; } = string.Empty;//泛型类型的名称
public string RName { get; set; } = string.Empty;
public MyClass()
{ }
public MyClass(string name, string mes, T t, R r)
{
Name = name;
Mes = mes;
TName = t.GetType().Name;
RName = r.GetType().Name;
}
public void MyMethod(IProgress<string> progress)
{
if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Mes))
{
progress?.Report($"你调用的是泛型类无参构造函数,泛型T名称:{typeof(T)},泛型R名称:{typeof(R)}。");
}
else
{
progress?.Report($"你调用的是泛型类有参构造函数,泛型T名称:{typeof(T)},泛型R名称:{typeof(R)}。");
}
}
//泛型方法
public void MyMethodU<U>(IProgress<string> progress, T t)
{
//只有使用新的泛型U的方法才称之为泛型方法,使用泛型T、R的都不能称之为泛型方法。
progress?.Report($"泛型类中泛型方法,泛型U名称:{typeof(U)},泛型T实例内容:{t}。");
}
}
二、开始生成模式实例,调用方法。
2.1 调用普通类中普通方法
void CreatMethodInClass(IProgress<string> progress)
{
//【1、创建普通类】
//typeFullName = 类的完全限定名(即包括命名空间)
string typeFullName = "LearnCreatClassByString.Models.MyClass";
object[] argsC = new object[] { "wxy", "HelloWorld" };//构造函数用的参数
Type? typeC = Type.GetType(typeFullName);
if (typeC != null)
{
var tC = Activator.CreateInstance(typeC, argsC);//调用带参构造函数
//var tC = Activator.CreateInstance(type, null);//调用无参构造函数
if (tC is MyClass p)
{
//【2、调用普通方法】
// 2-1、根据名称调用
MethodInfo? mio = typeC.GetMethod("MyMethod");
if (mio is MethodInfo mi)
{
object[] argsM = { progress };
mi.Invoke(p, argsM);
}
// 2-2、直接调用
p.MyMethod(progress);
}
else
{ }
}
else
{ }
}
2.2-调用普通类中泛型方法
void CreatTRMethodInClass(IProgress<string> progress)
{
//【1、创建普通类】
//typeFullName = 类的完全限定名(即包括命名空间)
string typeFullName = "LearnCreatClassByString.Models.MyClass";
object[] argsC = new object[] { "wxy", "HelloWorld" };//构造函数用的参数
Type? typeC = Type.GetType(typeFullName);
if (typeC != null)
{
var tC = Activator.CreateInstance(typeC, argsC);//调用带参构造函数
//var tC = Activator.CreateInstance(type, null);//调用无参构造函数
if (tC is MyClass p)
{
//【2、调用泛型方法】
// 2-1、根据名称调用
MethodInfo? mio = typeC.GetMethod("MyMethodTR");
if (mio is MethodInfo mi)
{
Type[] typeMArgs = { typeof(int), typeof(string) };
MethodInfo miConstructed = mi.MakeGenericMethod(typeMArgs);
object[] argsM = { progress };
miConstructed.Invoke(p, argsM);
}
// 2-2、直接调用
p.MyMethodTR<int, string>(progress);
}
else
{ }
}
else
{ }
}
2.3-调用泛型类中泛型方法
void CreatTRMethodInTRClass(IProgress<string> progress)
{
//【1、创建泛型类】
// 获取当前程序集
Assembly assembly = Assembly.GetExecutingAssembly();
//Assembly assembly = Assembly.Load("LearnCreatClassByString");//方式2
/*【关键】
* 获取泛型类的完全限定名(即包括命名空间)
* typeFullName第二个字符串中的【`2】表示泛型参数占位符个数。
* 一个泛型参数则表示为:`1,多个泛型参数则表示为:`N;
*/
string typeFullName = "LearnCreatClassByString.Models.MyClass" + "`2";
var genericC = assembly.GetType(typeFullName);
if (genericC != null)
{
Type[] typeCArgs = { typeof(string), typeof(string) };
Type constructedC = genericC.MakeGenericType(typeCArgs);
object[] argsC = new object[] { "wxy", "HelloWorld", "Twxy", "Rwxy" };
var tC = Activator.CreateInstance(constructedC, argsC);
if (tC is MyClass<string, string> p)
{
p.MyMethod(progress);
//【2、调用泛型方法】
// 2-1、根据名称调用
MethodInfo? mio = constructedC.GetMethod("MyMethodU");
if (mio is MethodInfo mi)
{
Type[] typeMArgs = { typeof(string) };
MethodInfo miConstructed = mi.MakeGenericMethod(typeMArgs);
string tString = "光使用泛型类泛型T、R的方法,不能称为泛型方法,需要有自己的泛型才能叫泛型方法。";
object[] argsM = { progress, tString };//第2个参数是:T t,T是泛型类中的T。
miConstructed.Invoke(p, argsM);
}
// 2-2、直接调用
progress.Report("方式2:直接调用泛型方法。");
p.MyMethodU<int>(progress, "直接调用泛型方法。");
}
else
{ }
}
else
{ }
}
三、参考文章
3.1-《c#根据字符串创建对象实例》
https://blog.csdn.net/xuwei_xuwei/article/details/36182041
3.2-《C# 根据字符串生成对象——使用反射》
https://blog.csdn.net/q__y__L/article/details/103159234
3.3-《C#如何根据字符串动态的创建对象(类)?》
https://bbs.csdn.net/topics/250049825
3.4-《C# 动态创建实例化泛型对象,实例化新对象 new()》
https://www.cnblogs.com/lfzm/p/9801367.html
3.5-《C# 通过反射来动态创建泛型类型》
https://www.cnblogs.com/mq0036/p/15346470.html
3.6-《MethodInfo.MakeGenericMethod(Type[]) 方法》
MethodInfo.MakeGenericMethod(Type[]) 方法 (System.Reflection) | Microsoft Learn

8873

被折叠的 条评论
为什么被折叠?



