c#调用dll里的某个方法,该方法返回值类型是dll里定义的一个类,该如何强转
[A]处的AppInfo在lib下的dll位置处,[B]处的AppInfo在 “我的源程序” 的Bin/debug/下的dll位置处,如何解决啊 展开
利用反射调用DLL,并使用DLL中的类创建对象,类型必须加全域名。
不过你的问题是不是这个原因需要排查,另外,你可以为你的类定义一个接口,返回后强制转换为接口试试。
我给你个,给定域名空间和DLL文件路径及文件名、类名,动态创建对象的构造类。看看有没有帮助。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
namespace ICom.CommonLib
{
/// <summary>
/// 使用应用程序域动态方式创建对象。
/// </summary>
public class ObjectConstructor : IDisposable,IObjectConstructor
{
#region 内部对象
AppDomain _Domain = null;
Hashtable _DomainHash = new Hashtable();
RemoteAssemblyFactory _RAF = null;
string _DomainName;
bool _Disposed;
#endregion
#region 构造函数
/// <summary>
/// 析构函数,释放内部对象。
/// </summary>
~ObjectConstructor()
{
Dispose(false);
}
#endregion
#region +属性
#region 状态消息
string _Message = "";
/// <summary>
/// 读取状态消息。
/// </summary>
public string Message
{
get { return _Message; }
}
#endregion
#endregion
#region 方法
/// <summary>
/// 创建应用程序域。
/// <param name="DomainName">应用域名。</param>
/// </summary>
/// <returns>成功标志。</returns>
public bool CreateDomain(string DomainName)
{
if (!CreateRemoteAssemblyFactory(DomainName)) return false;
_DomainName = DomainName;
return true;
}
/// <summary>
/// 动态创建对象。
/// <param name="DllFile">库文件路径和文件名。</param>
/// <param name="ObjectFullName">对象命名空间名及对象名称。</param>
/// </summary>
/// <returns>动态创建的对象或者空值(NULL)。</returns>
public object CreateObject(string DllFile,string ObjectFullName)
{
Assembly asm;
Type type;
object obj = null; ;
if (_RAF != null)
{
try
{
asm = _RAF.Create(DllFile);
type = asm.GetType(ObjectFullName);
obj = Activator.CreateInstance(type);
}
catch (Exception e)
{
_Message = e.Message;
}
}
return obj;
}
#region 释放对象
/// <summary>
/// 释放托管资源。
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放所有资源。
/// </summary>
/// <param name="disposing">Dispose调用标志。</param>
protected virtual void Dispose(bool disposing)
{
if (!_Disposed)
{
if (disposing)
{
if (_RAF != null) _RAF.Dispose();
if (_DomainHash.ContainsKey(_DomainName))
{
_Domain = (AppDomain)_DomainHash[_DomainName];
AppDomain.Unload(_Domain);
_DomainHash.Remove(_DomainName);
}
}
//非托管
_Disposed = true;
}
}
#endregion
#endregion
#region 局部函数
private bool CreateRemoteAssemblyFactory(string dmn)
{
AppDomainSetup setup = new AppDomainSetup();
string thisdll, nspc = this.GetType().Namespace;
setup.ShadowCopyFiles = "true";
_Domain = AppDomain.CreateDomain(dmn, null, setup);
_DomainHash.Add(dmn, _Domain);
thisdll = Assembly.GetExecutingAssembly().Location;
try
{
_RAF = (RemoteAssemblyFactory)_Domain.CreateInstanceFromAndUnwrap(thisdll, "ICom.CommonLib.RemoteAssemblyFactory");
return true;
}
catch (Exception e)
{
_Message = e.Message;
}
return false;
}
#endregion
}
/// <summary>
/// 远程程序集工厂。
/// </summary>
public class RemoteAssemblyFactory : MarshalByRefObject, IDisposable
{
Assembly _ASM = null;
bool _Disposed;
/// <summary>
/// 析构函数,释放内部对象。
/// </summary>
~RemoteAssemblyFactory()
{
Dispose(false);
}
/// <summary>
/// 创建远程程序集。
/// </summary>
/// <param name="dllFile">程序集所在DLL文件的路径和文件名。</param>
/// <returns>程序集对象或空值(NULL)。</returns>
public Assembly Create(string dllFile)
{
try
{
_ASM = Assembly.LoadFrom(dllFile);
return _ASM;
}
catch (Exception e)
{
throw e;
}
}
/// <summary>
/// 释放托管资源。
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放资源。
/// </summary>
/// <param name="disposing">Dispose调用标志。</param>
protected virtual void Dispose(bool disposing)
{
if (!_Disposed)
{
if (disposing)
{
_ASM = null;
}
//非托管
_Disposed = true;
}
}
}
}
这是个很常见的同结构同名类跨域互转问题。
假定A.Dll中有一个public ANameSpace.AppInfo SomeMethod()方法。
如果AppInfo在A.Dll中定义,同名同结构的AppInfo类在B.Dll中也有定义,那么不管你是使用using A还是反射得到一个A中AppInfo类型的值,都不允许在B中使用(BNameSpace.AppInfo)SomeMethod()进行类型转换,即使我们知道两个AppInfo结构是完全一样的。
取决于应用环境,一般会有以下几种处理方式。
如果A.Dll允许被using。不存在上述问题,直接在B中使用A中定义的AppInfo。
如果A.Dll不允许被using,但允许被有限度的修改。常见的解决方法,让AppInfo实现接口、或者将A中AppInfo更改为框架内置的数据类型比如List<>等、让A中AppInfo支持序列化/反序列化(XmlSerialization最佳/BinarySerialization亦可)都可以满足大部分需要,同时尽可能避免B的更改。
如果A.Dll不允许被using,也不允许被修改。必须通过反射实现类型转换。标准做法是在B中自写TypeConverter以提供object向B中AppInfo转换的功能(当然这里的object的实际类型是A中的AppInfo)。该类型转换器应能够通过反射获取必要的值并填充至新AppInfo对象的对应字段。以上操作本质上就是对象的浅表克隆。当然,偷懒的话在B中AppInfo类上多重载一个构造以从object获取初始值也行,但是依然是要依靠反射去访问你需要的属性并填充。
此外,类似问题我在另一处已作答,仅供参考:
如果以上已经确认但是依然出现问题
你可以继续用反射来访问返回的变量 不需要转换类型也能继续使用
我用的反射,别说其他的,谢谢