定义通用方法

时间:2012-06-22 14:22:40

标签: c# generics

全部,我有一个方法,当前用于调用返回类型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??";
        ...

我如何实现我想要的,或者我只是重载方法?

非常感谢你的帮助。

3 个答案:

答案 0 :(得分:6)

替换

return false;

通过

return default(T);

return Convert.ToBoolean(result);

通过

return (T)result;

答案 1 :(得分:4)

如果你没有从DLL获得真正的价值,你显然必须从某个地方创建一个值。对每种可能的类型T起作用的唯一方法是return default(T),它提供该类型的默认值(即0 intnull任何参考类型)。

如果在类型参数上放置类型约束,则可以获得更多选项,但这会牺牲通用性。

答案 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参数返回结果。