如何在 C#下利用反射动态创建对象

如何在 C#下利用反射动态创建对象,第1张

得到目标类的类型

反射

/// <summary>

/// 作者:武广敬

/// Blog:tonyepapercnblogscom

///

/// 反射

/// </summary>

public class MReference

{

/// <summary>

/// 得到类型

/// </summary>

/// <param name="consultClass">与要反射的类同一命名空间下的别一类型,用于得到完全限定名</param>

/// <param name="targetClassName">需要反射的类名</param>

/// <returns>反射得到的类型</returns>

public static Type getType(Type consultClass,string targetClassName)

{

//得到完全限定名

string assemblyQualifiedName = consultClassAssemblyQualifiedName;

//从完全限定名的第一个逗号开始得到完全限定名的公共部份

string assemblyInformation = assemblyQualifiedNameSubstring(assemblyQualifiedNameIndexOf(","));

try

{

//根据要反射的类名+截取后的限定名得到要反射类的类型

Type ty = TypeGetType(targetClassName + assemblyInformation);

return ty;

}

catch (Exception ex)

{

return null;

}

}

}

表单工厂

/// 作者:武广敬

/// Blog:tonyepapercnblogscom

/// 表单工厂

/// </summary>

public class FormFactory

{

/// <summary>

/// 根据传入的数据库名,返回一个表单的实例

/// </summary>

/// <param name="tableName">数据库的表名</param>

/// <returns>与此表相对应的表单对象</returns>

public static Form GetInstance(string tableName)

{

//与目标对象类型相同命名空间的类型

Type sourceType = typeof(MasterSoftWinUIfrmMain);

//目标对象类型全名(包括命名空间)

string className = "MasterSoftWinUIfrm" + tableName;

//如果表名为空抛出异常

if (stringIsNullOrEmpty(tableName))

throw new ArgumentNullException("tableName");

return GetInstance(sourceType, className) as Form;

}

/// <summary>

/// 得到对象

/// </summary>

/// <param name="sourceType">与目标对象类型相同命名空间的类型</param>

/// <param name="className">//目标对象类型全名(包括命名空间)</param>

/// <returns>反射得到的对象</returns>

private static object GetInstance(Type sourceType, string className)

{

try

{

//根据传入的表名得到对应窗体的类型 MasterSoftWinUIfrmMain是相同命名空间下的一个类型,用于得到限定名

Type ty = MReferencegetType(sourceType, className);

if (ty == null)

throw new ArgumentNullException("ty");

//得到类型的 GetInstance 方法(当然这个类型必须有这个静态方法-单例模式)

MethodInfo getInstance = tyGetMethod("GetInstance");

if (getInstance == null)

throw new ArgumentNullException("getInstance");

//调用GetInstance静态方法

object obj = (MdiChildEditForm)getInstanceInvoke(null, null);

//IMdiChildEditForm frm = ((IMdiChildEditForm)SystemActivatorCreateInstance(ty))GetInstance();

//返回得到的窗体

return obj;

}

catch (Exception ex)

{

throw ex;

}

}

}

调用方法

Form frm = (Form)FormFactoryGetInstance(tableName);

frmShow();

反射通常具有以下用途:

使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。

使用 Module 发现以下信息:包含模块的程序集以及模块中的类等。您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。

使用 ConstructorInfo 发现以下信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。

使用 MethodInfo 发现以下信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。

使用 FieldInfo 发现以下信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。

使用 EventInfo 发现以下信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。

使用 PropertyInfo 发现以下信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。

使用 ParameterInfo 发现以下信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。

当您在一个应用程序域的仅反射上下文中工作时,请使用 CustomAttributeData 来了解有关自定义属性的信息。使用 CustomAttributeData,您不必创建属性的实例就可以检查它们。

SystemReflectionEmit 命名空间的类提供了一种特殊形式的反射,使您能够在运行时生成类型。

反射也可用于创建称作类型浏览器的应用程序,它使用户能够选择类型,然后查看有关选定类型的信息。

反射还有其他一些用途。JScript 等语言编译器使用反射来构造符号表。SystemRuntimeSerialization 命名空间中的类使用反射来访问数据并确定要持久保存的字段。SystemRuntimeRemoting 命名空间中的类通过序列化来间接地使用反射

这里用的是一个单件模式,

GetProvider()这个方法,用来生成一个IDataProvider接口的实例化对象,中间应用了反射方法,下面这行:

instance = (IDataProvider)ActivatorCreateInstance(TypeGetType(stringFormat("MusicData{0}DataProvider,MusicData{0}", ConfigsGetDbType), false, true));

调用反射创建满足接口IDataProvider的类,赋给instance。类似于平常编写的IdataProvider instance=new MusicDataAccessDataProvider();这种方式。但应用反射的方式,这样使代码更容易配置,更加灵活。如这里,可以创建多种数据库的访问方式,实现IDataProvider,然后在配置文件中写入当前应用的数据库类名信息,就可以通过反射创建具体的类。上面那句的ConfigsGetDbType用来获取当前配置文件中的当前数据库信息,返回的是你填写的信息,如SqlServer、Access、MySql,具体代码我看不到,但原理是这样的。

你填写的信息应该满足:

MusicData命名空间DataProvider

也就是比如你有一个Access数据访问方式

你应该新建一个类库:格式为

namespace MusicData命名空间

{

class DataProvider:IDataProvider

{

//这个类必须实现IDataProvider接口

}

}

注意:命名空间你替换成你的,比如Access,SqlServer等

这个类库生成的dll你应该命名成 MusicData命名空间dll 命名空间就是你配置文件的标识,你配置文件中填写你上面定的命名空间就行了。

又如,你还有一个SqlServer方式访问的数据库:

那么新建类库

namespace MusicDataSqlServer

{

class DataProvider:IDataProvider

{

//这个类必须实现IDataProvider接口

}

}

生成dll为MusicDataSqlServerdll

如果还有其他数据库访问途径,类似方法

建其他的类库

配置文件中写上Access/SqlServer或者其他,

要和你的命名空间保持一致。因为反射时是根据命名空间+类名的方式创建对象的,如代码中的:

TypeGetType(stringFormat("MusicData{0}DataProvider,MusicData{0}", ConfigsGetDbType)

里面的字符串就是你要创建的类的完整名字:

格式为:

TypeGetType("类完整名,程序集名");

类完整名=命名空间名+类名

下面的方法:

IDataProvider GetInstance()

就是使用单件模式,获取一个IDataProvider

里面使用了锁,防止多线程同时进行时冲突,这里面进行了判断,如果_instance为空就用上面的函数创建一个新的,然后返回。

最后一个方法是释放对象。

有时间去网上搜点反射方面的例子,单件模式应该很容易看懂的,就是用一个静态私有变量,只保持一个实例对象_instance存在。

建议研究一下PetShop源代码,然后关于三层和反射工厂就会有一个新的认识。

以上就是关于如何在 C#下利用反射动态创建对象全部的内容,包括:如何在 C#下利用反射动态创建对象、c#中什么是反射,他有什么优点和作用能否举个生动点的例子、public static IDataProvider GetInstance()等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9614884.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存