全部,我有一个方法,当前用于调用返回类型bool
的DLL,这很好用。
public static bool InvokeDLL(string strDllName, string strNameSpace,
string strClassName, string strMethodName,
ref object[] parameters,
ref string strInformation,
bool bWarnings = false)
{
try
{
// Check if user has access to requested .dll.
if (!File.Exists(Path.GetFullPath(strDllName)))
{
strInformation = String.Format("Cannot locate file '{0}'!",
Path.GetFullPath(strDllName));
return false;
}
else
{
// Execute the method from the requested .dll using reflection.
Assembly DLL = Assembly.LoadFrom(Path.GetFullPath(strDllName));
Type classType = DLL.GetType(String.Format("{0}.{1}",
strNameSpace, strClassName));
if (classType != null)
{
object classInstance = Activator.CreateInstance(classType);
MethodInfo methodInfo = classType.GetMethod(strMethodName);
if (methodInfo != null)
{
object result = null;
result = methodInfo.Invoke(classInstance, new object[] { parameters });
return Convert.ToBoolean(result);
}
}
// Invocation failed fatally.
strInformation = String.Format("Could not invoke the requested DLL '{0}'! " +
"Please insure that you have specified the namespace, class name " +
"method and respective parameters correctly!",
Path.GetFullPath(strDllName));
return false;
}
}
catch (Exception eX)
{
strInformation = String.Format("DLL Error: {0}!", eX.Message);
if (bWarnings)
Utils.ErrMsg(eX.Message);
return false;
}
}
现在,我想扩展此方法,以便我可以从任何类型的DLL中检索返回值。我计划使用泛型来做这件事,但我立即进入了我不知道的领域。如果在编译时未知,我如何返回T,我已经查看了反射,但我不确定在这种情况下如何使用它。在上面的代码中进行第一次检查
public static T InvokeDLL<T>(string strDllName, string strNameSpace,
string strClassName, string strMethodName,
ref object[] parameters, ref string strInformation,
bool bWarnings = false)
{
try
{
// Check if user has access to requested .dll.
if (!File.Exists(Path.GetFullPath(strDllName)))
{
strInformation = String.Format("Cannot locate file '{0}'!",
Path.GetFullPath(strDllName));
return "WHAT/HOW??";
...
我如何实现我想要的,或者我只是重载方法?
非常感谢你的帮助。
答案 0 :(得分:6)
替换
return false;
通过
return default(T);
和
return Convert.ToBoolean(result);
通过
return (T)result;
答案 1 :(得分:4)
如果你没有从DLL获得真正的价值,你显然必须从某个地方创建一个值。对每种可能的类型T
起作用的唯一方法是return default(T)
,它提供该类型的默认值(即0
int
,null
任何参考类型)。
如果在类型参数上放置类型约束,则可以获得更多选项,但这会牺牲通用性。
答案 2 :(得分:2)
我会做这样的事情:
public static InvokeDLLResult<T> InvokeDLL<T>(string strDllName, string strNameSpace,
string strClassName, string strMethodName,
ref object[] parameters,
ref string strInformation,
bool bWarnings = false)
{
try
{
// Check if user has access to requested .dll.
if (!File.Exists(Path.GetFullPath(strDllName)))
{
strInformation = String.Format("Cannot locate file '{0}'!",
Path.GetFullPath(strDllName));
return InvokeDLLResult<T>.Failure;
}
else
{
// Execute the method from the requested .dll using reflection.
Assembly DLL = Assembly.LoadFrom(Path.GetFullPath(strDllName));
Type classType = DLL.GetType(String.Format("{0}.{1}", strNameSpace, strClassName));
if (classType != null)
{
object classInstance = Activator.CreateInstance(classType);
MethodInfo methodInfo = classType.GetMethod(strMethodName);
if (methodInfo != null)
{
object result = null;
result = methodInfo.Invoke(classInstance, new object[] { parameters });
return new InvokeDLLResult<T>(true, (T) Convert.ChangeType(result, methodInfo.ReturnType));
}
}
// Invocation failed fatally.
strInformation = String.Format("Could not invoke the requested DLL '{0}'! " +
"Please insure that you have specified the namespace, class name " +
"method and respective parameters correctly!",
Path.GetFullPath(strDllName));
return InvokeDLLResult<T>.Failure;
}
}
catch (Exception eX)
{
strInformation = String.Format("DLL Error: {0}!", eX.Message);
if (bWarnings)
Debug.WriteLine(eX.Message);
return InvokeDLLResult<T>.Failure;
}
}
public class InvokeDLLResult<T>
{
public InvokeDLLResult(bool success, T result)
{
Success = success;
Result = result;
}
public bool Success { get; private set; }
public T Result { get; private set; }
public static InvokeDLLResult<T> Failure = new InvokeDLLResult<T>(false, default(T));
}
或者,我会写一个TryInvokeDLL方法,使用out参数返回结果。