C# 作为方法参数和查看字段的泛型接口

C# 作为方法参数和查看字段的泛型接口,c#,C#,这可能是我幼稚的表现,但无论如何 我有一个通用接口,它定义了一组跨实现的标准方法(实现方式不同) 我将接口作为参数传递给一个方法,该方法负责持久化到数据库。例如,我有一些从通用接口(称为IEntry)定义的称为bug、incident等的实现。这些相关实现还使用IEnumerable 因为bug与事件不同,所以有不同的字段。当我将接口作为参数传递到方法中时,是否有任何方法可以推断类型?因此,如果我传入Bug对象,我可以使用它的字段,这些字段与Incident中的字段不同。这些字段对于数据库的持久

这可能是我幼稚的表现,但无论如何

我有一个通用接口,它定义了一组跨实现的标准方法(实现方式不同)

我将接口作为参数传递给一个方法,该方法负责持久化到数据库。例如,我有一些从通用接口(称为IEntry)定义的称为bug、incident等的实现。这些相关实现还使用IEnumerable

因为bug与事件不同,所以有不同的字段。当我将接口作为参数传递到方法中时,是否有任何方法可以推断类型?因此,如果我传入Bug对象,我可以使用它的字段,这些字段与Incident中的字段不同。这些字段对于数据库的持久性非常有用。我假设没有,因为没有办法知道要传递的类型(显然),但我知道这里的人更有智慧。在这种情况下,有没有更好的做事方式?由于相似性,我希望坚持使用接口

编辑:我想另一种方法是使用一些流控制动态生成sql语句,然后将其作为参数传入


谢谢

关于传递对象和接口的事情是,您真的不应该关心实际的类型,只要它继承/实现您感兴趣的特定基类/接口

因此,将逻辑构建到该方法中,以确定它是一个bug,然后访问只针对bug出现的东西,这基本上不是OOP方式,尽管它可能是特定情况下的“最佳”方式

但是,我建议不要这样做,而是尝试用多态性构建一种适当的OOP方法来处理差异,而不是将其作为特殊情况构建到方法中


提到持久性,这个方法负责将数据存储到某个地方吗?也许您可以将收集要存储的信息的部分与存储信息的部分分开,这样您就可以要求对象本身为您提供所有相关信息,这些信息可能因类而异。

持久性只是类中将详细信息上载到数据库的方法

我想我可以为持久性需求编写一个带有函数的抽象类,该类可以基于参数来工作。我可以在我的每个接口实现中使用它。由于数据库更新的方式(几乎相同,但sql查询中只有几句话发生了更改),因此我可以根据方法参数生成它。

糟糕的设计(如问题中所述):

公共接口
{
字符串说明{get;set;}
}
公共类错误:IEntry
{
公共int ID{get;set;}
公共字符串说明{get;set;}
公共字符串用户名{get;set;}
}
公开课事件:IEntry
{
公共Guid ID{get;set;}
公共字符串说明{get;set;}
}
公共类持久器
{
公共void保存(IEnumerable值)
{
foreach(值中的值){Save(value);}
}
公共作废保存(IEntry值)
{
如果(值为Bug){/*Bug保存逻辑*/}
else if(值为事件){/*事件保存逻辑*/}
}
}
改进设计(智能实体方法):

公共接口
{
字符串说明{get;set;}
作废保存(IPerster网关);
}
公共类错误:IEntry
{
公共int ID{get;set;}
公共字符串说明{get;set;}
公共字符串用户名{get;set;}
公共作废保存(IPerster网关)
{
gateway.SaveBug(this);
}
}
公开课事件:IEntry
{
公共Guid ID{get;set;}
公共字符串说明{get;set;}
公共作废保存(IPerster网关)
{
网关。保存事件(本);
}
}
公共接口IPersister
{
void SaveBug(Bug值);
无效事件(事件值);
}
公共类持久器:iperster
{
公共void保存(IEnumerable值)
{
foreach(值中的值){Save(value);}
}
公共作废保存(IEntry值)
{
保存(这个);
}
公共void SaveBug(Bug值)
{
//错误保存逻辑
}
公共事件(事件值)
{
//事件保存逻辑
}
}
改进后的设计只是为了满足改变Persister.Save(IEntry)的需要。我只是想演示使代码不那么脆弱的第一步。在实际代码和生产代码中,您可能希望有一个BugPersister和IncidentPersister类,以便符合

希望这个以代码为中心的例子能有所帮助

public interface IEntry
{
    string Description { get; set; }
}
public class Bug : IEntry
{
    public int ID { get; set; }
    public string Description { get; set; }
    public string UserName { get; set; }
}
public class Incident : IEntry
{
    public Guid ID { get; set; }
    public string Description { get; set; }
}

public class Persister
{
    public void Save(IEnumerable<IEntry> values)
    {
        foreach (IEntry value in values) { Save(value); }
    }

    public void Save(IEntry value)
    {
        if (value is Bug) { /* Bug save logic */ }
        else if (value is Incident) { /* Incident save logic */ }
    }
}
public interface IEntry
{
    string Description { get; set; }
    void Save(IPersister gateway);
}

public class Bug : IEntry
{
    public int ID { get; set; }
    public string Description { get; set; }
    public string UserName { get; set; }

    public void Save(IPersister gateway)
    {
        gateway.SaveBug(this);
    }
}

public class Incident : IEntry
{
    public Guid ID { get; set; }
    public string Description { get; set; }

    public void Save(IPersister gateway)
    {
        gateway.SaveIncident(this);
    }
}

public interface IPersister
{
    void SaveBug(Bug value);
    void SaveIncident(Incident value);
}

public class Persister : IPersister
{
    public void Save(IEnumerable<IEntry> values)
    {
        foreach (IEntry value in values) { Save(value); }
    }

    public void Save(IEntry value)
    {
        value.Save(this);
    }

    public void SaveBug(Bug value)
    {
        // Bug save logic
    }

    public void SaveIncident(Incident value)
    {
        // Incident save logic
    }
}