Reputation: 23831
All, I have a method that is currently used to invoke DLLs of return type bool
, this works great. This method is
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;
}
}
Now, I want to extend this method so that I can retrieve return values from a DLL of any type. I planned to do this using generics but immediately have gone into territory unknown to me. How do I return T when it is unknown at compile time, I have looked at reflection but I am unsure how it would be used in this case. Take the first check in the above code
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??";
...
How can I achieve what I want, or shall I just overload the method?
Thanks very much for your help.
Upvotes: 5
Views: 494
Reputation: 4736
I would do something like this:
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));
}
Or, I would write a TryInvokeDLL method, using an out parameter to return the result.
Upvotes: 2
Reputation: 9969
When you've not got a real value from the DLL, you obviously have to create a value from somewhere. The only way that works for every possible type T
is return default(T)
which gives whatever the default value for that type is (i.e. 0
for int
, null
for any reference type).
If you place type constraints on the type parameter you can get more options, but at the expense of genericity.
Upvotes: 4
Reputation: 172468
Replace
return false;
by
return default(T);
and
return Convert.ToBoolean(result);
by
return (T)result;
Upvotes: 6