Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# T实现接口的通用方法<;T>;_C#_Generics_Inheritance_Interface - Fatal编程技术网

C# T实现接口的通用方法<;T>;

C# T实现接口的通用方法<;T>;,c#,generics,inheritance,interface,C#,Generics,Inheritance,Interface,我正在尝试创建一个通用的数据检索过程。我目前所做的一切都是可行的,但其中有一部分似乎并不正确,我希望有更好的方法来实现它 我的想法是为数据库中的每个表都有类,下面是一个类的示例: public class CMCGRGRGROUP : IFacetsObject<CMCGRGRGROUP> { public int GRGR_CK { get; set; } public string GRGR_NAME { get; set; } public string

我正在尝试创建一个通用的数据检索过程。我目前所做的一切都是可行的,但其中有一部分似乎并不正确,我希望有更好的方法来实现它

我的想法是为数据库中的每个表都有类,下面是一个类的示例:

public class CMCGRGRGROUP : IFacetsObject<CMCGRGRGROUP>
{
    public int GRGR_CK { get; set; }
    public string GRGR_NAME { get; set; }
    public string GRGR_ADDR1 { get; set; }

    public IEnumerable<CMCGRGRGROUP> ToObject(DataTable table)
    {
        return table.AsEnumerable().Select(row =>
        {
            return new CMCGRGRGROUP
            {
                GRGR_CK = Convert.ToInt32(row["GRGR_CK"]),
                GRGR_NAME = row["GRGR_NAME"].ToString(),
                GRGR_ADDR1 = row["GRGR_ADDR1"].ToString()
            };
        });
    }
}
下面是我用来执行查询的方法:

public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) where T : new()
{
    using (var conn = new AseConnection(_conn))
    {
        conn.Open();
        var cmd = new AseCommand(sql, conn);

        var dt = new DataTable();
        var da = new AseDataAdapter(sql, conn);
        da.Fill(dt);                

        return obj.ToObject(dt); //this is the interface method
    }
}
这样称呼它:

return T.ToObject(dt);
var result = ExecuteQuery<CMCGRGRGROUP>(sql).Take(5);
var result = ExecuteQuery<CMCGRGRGROUP>(sql, new CMCGRGRGROUP()).Take(5);
public interface IFacetsObject<T> where T : IFacetsObject<T>
{
    IEnumerable<T> ToObject(DataTable obj);
}
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) 
    where T : IFacetsObject<T>, new()
var result=ExecuteQuery(sql).Take(5);
而不是像这样:

return T.ToObject(dt);
var result = ExecuteQuery<CMCGRGRGROUP>(sql).Take(5);
var result = ExecuteQuery<CMCGRGRGROUP>(sql, new CMCGRGRGROUP()).Take(5);
public interface IFacetsObject<T> where T : IFacetsObject<T>
{
    IEnumerable<T> ToObject(DataTable obj);
}
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) 
    where T : IFacetsObject<T>, new()
var result=ExecuteQuery(sql,new-cmcgrgroup()).Take(5);

我承认我还不太熟悉泛型,所以实现中可能有一些不正确的地方。

您需要在接口上设置泛型约束。声明如下:

return T.ToObject(dt);
var result = ExecuteQuery<CMCGRGRGROUP>(sql).Take(5);
var result = ExecuteQuery<CMCGRGRGROUP>(sql, new CMCGRGRGROUP()).Take(5);
public interface IFacetsObject<T> where T : IFacetsObject<T>
{
    IEnumerable<T> ToObject(DataTable obj);
}
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) 
    where T : IFacetsObject<T>, new()
公共接口IFacetsObject其中T:IFacetsObject
{
IEnumerable对象(DataTable对象);
}
为了使其生效,您还必须更改您的声明,如下所示:

return T.ToObject(dt);
var result = ExecuteQuery<CMCGRGRGROUP>(sql).Take(5);
var result = ExecuteQuery<CMCGRGRGROUP>(sql, new CMCGRGRGROUP()).Take(5);
public interface IFacetsObject<T> where T : IFacetsObject<T>
{
    IEnumerable<T> ToObject(DataTable obj);
}
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) 
    where T : IFacetsObject<T>, new()
public IEnumerable ExecuteQuery(字符串sql,IFacetsObject obj)
其中T:IFacetsObject,new()

您可以在ExecuteQuery方法上添加约束。你已经有了一个:要求它不能是新的。您可以这样声明:

public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) 
  where T : IFacetsObject<T>, new()
{
    using (var conn = new AseConnection(_conn))
    {
        conn.Open();
        var cmd = new AseCommand(sql, conn);

        var dt = new DataTable();
        var da = new AseDataAdapter(sql, conn);
        da.Fill(dt);                

        return obj.ToObject(dt); //this is the interface method
    }
}
public IEnumerable ExecuteQuery(字符串sql,IFacetsObject obj)
其中T:IFacetsObject,new()
{
使用(var conn=新ASE连接(_conn))
{
conn.Open();
var cmd=新命令(sql,conn);
var dt=新数据表();
var da=新的AseDataAdapter(sql,conn);
da.填充(dt);
返回obj.ToObject(dt);//这是接口方法
}
}
所以它现在知道T是一个
IFacetsObject
。你现在可以做:

public IEnumerable<T> ExecuteQuery<T>(string sql) 
  where T : IFacetsObject<T>, new()
{
    using (var conn = new AseConnection(_conn))
    {
        conn.Open();
        var cmd = new AseCommand(sql, conn);

        var dt = new DataTable();
        var da = new AseDataAdapter(sql, conn);
        da.Fill(dt);                

        return new T().ToObject(dt); //this is the interface method
    }
}
公共IEnumerable可执行程序(字符串sql) 其中T:IFacetsObject,new() { 使用(var conn=新ASE连接(_conn)) { conn.Open(); var cmd=新命令(sql,conn); var dt=新数据表(); var da=新的AseDataAdapter(sql,conn); da.填充(dt); return new T().ToObject(dt);//这是接口方法 } } 我觉得还是挺难看的

编辑响应:


请注意,您不能调用T.ToObject-接口不能定义静态方法。解决方法是使用new创建T的新实例并调用instance方法。

我看到您使用orkish变量命名约定是的,它们很糟糕-不幸的是,没有命名db表只是为了保持名称一致。您不能从接口继承,请注意。(接口被实现,行为/实现被继承)@sehe技术上接口可以从其他接口继承。感谢链接@DavidHaney,我可以看出,未来的开发人员在最初理解和/或实现模式时可能会遇到困难,并且可能会产生意外的后果,但无法根据所使用的模式“正确”实现接口。也就是说,这个特定的项目不需要对这一部分进行太多维护(例如添加新类),因此我认为简化更有可能更改的区域(查询)更有利。我肯定会为类定义提供有用的注释。我想问题是关于泛型方法的,而不是如何约束接口。它可能很难看,但我想这就是我想要的。谢谢!