C# 作为方法参数和查看字段的泛型接口
这可能是我幼稚的表现,但无论如何 我有一个通用接口,它定义了一组跨实现的标准方法(实现方式不同) 我将接口作为参数传递给一个方法,该方法负责持久化到数据库。例如,我有一些从通用接口(称为IEntry)定义的称为bug、incident等的实现。这些相关实现还使用IEnumerable 因为bug与事件不同,所以有不同的字段。当我将接口作为参数传递到方法中时,是否有任何方法可以推断类型?因此,如果我传入Bug对象,我可以使用它的字段,这些字段与Incident中的字段不同。这些字段对于数据库的持久性非常有用。我假设没有,因为没有办法知道要传递的类型(显然),但我知道这里的人更有智慧。在这种情况下,有没有更好的做事方式?由于相似性,我希望坚持使用接口 编辑:我想另一种方法是使用一些流控制动态生成sql语句,然后将其作为参数传入C# 作为方法参数和查看字段的泛型接口,c#,C#,这可能是我幼稚的表现,但无论如何 我有一个通用接口,它定义了一组跨实现的标准方法(实现方式不同) 我将接口作为参数传递给一个方法,该方法负责持久化到数据库。例如,我有一些从通用接口(称为IEntry)定义的称为bug、incident等的实现。这些相关实现还使用IEnumerable 因为bug与事件不同,所以有不同的字段。当我将接口作为参数传递到方法中时,是否有任何方法可以推断类型?因此,如果我传入Bug对象,我可以使用它的字段,这些字段与Incident中的字段不同。这些字段对于数据库的持久
谢谢关于传递对象和接口的事情是,您真的不应该关心实际的类型,只要它继承/实现您感兴趣的特定基类/接口 因此,将逻辑构建到该方法中,以确定它是一个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
}
}