【问题标题】:How to return a different object depending on IF in C# (Generics)如何根据 C#(泛型)中的 IF 返回不同的对象
【发布时间】:2019-01-29 14:02:02
【问题描述】:

我有一个 ASP.NET MVC(非核心)项目,在该项目中遇到了一些问题,我认为最终开始学习如何正确使用泛型可以解决我的问题。

我的情况是我有一个 SQL 连接,它返回数据,并且根据 SQL 中一个字段的结果,我想使用两种不同的模型。这些模型有很多共同的属性,所以我认为最好的做法是创建一个方法来选择要创建的模型,填写差异,返回模型,然后继续填写“共同”属性。

我曾尝试阅读一些有关泛型的内容,但我对此很陌生,所以我没有取得任何重大进展。

我的代码示例如下所示:

public ResultVM MainClass()
{
    var resultData = new ResultVM();

    // ... SQL returns data

    while (reader.Read())
    {
        resultData.Add(reader);
    }

    return resultData;
}

public object CreateObject(SqlDataReader indata)
{

    if((indata["Associate"].ToString()) == "0")
    {
        var individual = new Individual();
    }
    else
    {
        var group = new Group();
    }

    return object;
}

如何动态(取决于Associate 字段的值)创建个人或组?

【问题讨论】:

  • 让事情变得简单,使用两种不同的方法[CreateAssociateObject()CreateGroupObject()]并避免不必要的转换
  • 那绝对是最好的做事方式?由于它们有很多共同点,这意味着我会重复很多次。
  • 那你为什么不用那些常见的东西创建一个Interface呢?
  • 是的@sujithkarivelil 是正确的创建接口并返回它的引用或创建基类以返回它
  • 如果两个模型可以是有意义的基类的子类,您可以创建一个基类并将公共属性移到那里。但我在这里闻到了一些错误的设计决定。你能解释一下你想要做什么吗?为什么你有一些要求?

标签: c# asp.net-mvc dynamic-programming


【解决方案1】:

如何实现一个具有所有通用属性的接口?

类似

interface IInterface
{
    string CommonProperty1 { get; set; }
    string CommonProperty2 { get; set; }
}

class Individual : IInterface
{
    // ...
}

class Group : IInterface
{
    // ...
}

public IInterface CreateObject(SqlDataReader indata)
{
    if((indata["Associate"].ToString()) == "0")
    {
        var individual = new Individual();
        // ...  
        return individual;
    }
    else
    {
        var group = new Group();
        // ...
        return group;
    }
}

【讨论】:

  • 如果它们有共同的属性,我认为基类而不是接口会更合适。
【解决方案2】:

在您的情况下,我建议直接使用 System.Type。这里可以为您的问题提供多种更优雅的解决方案,具体取决于您的实际需要:

  1. indata.GetFieldType(int ordinal) 将返回您的字段的 .NET 类型
  2. Serialize data with type handling,那么你可以在非泛型反序列化后简单地获取类型。例如:

    var result = JsonConvert.DeserializeObject(dataJson);
    

result 将具有您的实际对象类型的类型。您可以检查它写入 result.GetType() 并创建此类型的对象。更高级的使用见Activator.CreateInstance(...)

  1. 在大多数情况下使用接口是最好的方法:

    interface ISomething
    {
        // ...
    }
    
    class Individual : ISomething
    {
        // ...
    }
    
    class Group : ISomething
    {
        // ...
    }
    

然后你用这种方式构建你的非泛型方法:

public ISomething CreateObject(SqlDataReader indata) 
{
    if((indata["Associate"].ToString()) == "0")
        return new Individual();
    else
        return new Group();
}

您的通用对象创建可能如下所示:

public T CreateObject<T>(SqlDataReader indata) 
{
    var o = new T();
    return o;
}

T 是类型,您在此方法之外传递:CreateObject&lt;YourType&gt;(indata) T 可以是您想要的任何类型,包括接口。在使用泛型时,您可能需要使用 is 关键字检查类型,但我建议使用接口并完全避免 is 检查。 示例:

if(yourObject is YourType)
{
    (yourObject as YourType).SomeSpecificToYourTypeMethod();
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多