【问题标题】:C# How to return instance dynamically by genericC#如何通过泛型动态返回实例
【发布时间】:2016-10-28 22:53:20
【问题描述】:

查看我的代码

class Program
{
    static void Main(string[] args)
    {
        Employee T = GetInstance<Importance.Employee>(Importance.Employee);
    }

    public static T GetInstance<T>(Importance objType)
    {
        if (objType == Importance.Employee)
            return (T)Convert.ChangeType((new Employee()), typeof(T));
        else 
            return (T)Convert.ChangeType((new Teacher()), typeof(T));
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

enum Importance
{
    Employee,
    Teacher
};

这条线不工作:

Employee emp = GetInstance<Importance.Employee>(Importance.Employee);

抛出错误

“GenericFunction.Importance.Employee”是一个“字段”,但用作“类型”

我在哪里犯了错误。请帮忙,因为我正在尝试学习通用,因为我在那里很弱。谢谢

【问题讨论】:

标签: c#


【解决方案1】:

正如Gilad Green 所说,您正在使用value 作为type。您可以执行以下操作:

class Program
{
    static void Main(string[] args)
    {
        Employee employee = GetInstance<Employee>(Importance.Employee);
        Teacher teacher = GetInstance<Teacher>(Importance.Teacher);

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>(Importance objType)
    {
        if (objType == Importance.Employee)
            return (T)Convert.ChangeType((new Employee()), typeof(T));
        else
            return (T)Convert.ChangeType((new Teacher()), typeof(T));
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

enum Importance
{
    Employee,
    Teacher
};

但是,正如我所见,如果您只想要给定类型的新对象,则不需要 Importance 枚举。您可以执行以下操作:

class Program
{
    static void Main(string[] args)
    {
        Employee employee = GetInstance<Employee>();
        Teacher teacher = GetInstance<Teacher>();

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>() where T : class, new()
    {
        return new T();
    }
}

public class Employee
{
    string ID = "";
    string Name = "";
}

public class Teacher
{
    string ID = "";
    string Name = "";
}

我们可以再想一想,给出两个样本。一个是 Enum,一个是多态性。

如果你真的想保留Enum,那么我认为你的泛型类型带有 Enum 参数只是为了确保它不会返回不同的类型,所以它会是这样的:

class Program
{
    static void Main(string[] args)
    {
        var employee = GetInstance<Employee>(Importance.Employee);
        var teacher = GetInstance<Teacher>(Importance.Teacher);

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>(Importance importance) where T : Role, new()
    {
        if (typeof(T) == typeof(Employee) && importance != Importance.Employee)
        {
            throw new InvalidCastException();
        }

        if (typeof(T) == typeof(Teacher) && importance != Importance.Teacher)
        {
            throw new InvalidCastException();
        }

        return new T();
    }
}

public abstract class Role { }

public class Employee : Role
{
    string ID = "";
    string Name = "";
}

public class Teacher : Role
{
    string ID = "";
    string Name = "";
}

public enum Importance
{
    Teacher,
    Employee
}

但我认为这没有意义。我会做类似的事情:

class Program
{
    static void Main(string[] args)
    {
        var employee = GetInstance<Employee>();
        var teacher = GetInstance<Teacher>();

        Console.WriteLine(employee.GetType());
        Console.WriteLine(teacher.GetType());

        Console.ReadKey();
    }

    public static T GetInstance<T>() where T : Role, new()
    {
        var role = new T();
        // do something important here

        return role;
    }
}

public abstract class Role { }

public class Employee : Role
{
    string ID = "";
    string Name = "";
}

public class Teacher : Role
{
    string ID = "";
    string Name = "";
}

【讨论】:

  • 虽然这可行,但我建议您查看我的更新以了解为什么不推荐这种设计
  • 你为什么返回这个throw new InvalidCastException();
【解决方案2】:

当这样使用它时,您实际上是在使用 Employee 的值来寻址您的 Importance 枚举 - 这不是一个类型,而是一个值。

不要以这种方式定义方法,而是添加Role的基类:

public class Role
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Employee : Role
{
}

public class Teacher : Role
{
}

以及方法:

public static Role GetInstance(Importance objType)
{
    if (objType == Importance.Employee)
        return new Employee();
    else
        return new Teacher();
}

这基本上是Factory design pattern


在您的场景中,让方法泛型然后传递枚举值以确定要实例化的类型是没有意义的。此外,在您当前的实现中,如果您将T 作为TeacherImportance.Employee 值传递:

var obj = Convert.ChangeType((new Employee()), typeof(Teacher));

你会得到:

InvalidCastException - 对象必须实现 IConvertible

决定你想做什么。如果你想要一个像枚举(和上面的例子)这样的映射值或者一个获取T 类型的泛型函数来实例化:

public static TRole GetInstance<TRole>() where TRole : Role, new()
{
    return new TRole();
}

Employee T = GetInstance<Employee>();

【讨论】:

  • 我是GetInstance函数的返回类型和参数应该是T。还告诉我当GetInstance函数的返回类型和参数是T时如何调用GetInstance函数。如果可能的话,发布另一个版本的代码。谢谢
猜你喜欢
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多