2015-02-11 45 views
0

比方说,我有以下几点:泛型类

public class DataType1 
{ 
    public DataType1() { } 

    public string Read() { return "dt1"; } 
} 

public class DataType2 
{ 
    public DataType2() { } 

    public string Read() { return "dt2"; } 
} 

和公用类:

然后,在我的主要应用程序:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test1 = new Logger<DataType1>(); 
     test1.Read(); // I want this to equal "dt1"; 

     var test2 = new Logger<DataType2>(); 
     test2.Read(); // I want this to equal "dt2"; 
    } 
} 

我认识到,我正在尝试做一种协变。但是,我不能从Logger继承DataType1/DataType2 - 这会违反体系结构(即DataType1/DataType2位于DAL,程序员需要通过Logger才能访问DAL)。

有关如何完成此任务的任何想法?

谢谢。

+0

'类记录仪其中T:SomeInterfaceWithReadMethod' – leppie 2015-02-11 05:53:02

回答

1

使用接口:

public class DataType1 : IReadable 
{ 
    public DataType1() { } 

    public string Read() { return "dt1"; } 
} 

public class DataType2 : IReadable 
{ 
    public DataType2() { } 

    public string Read() { return "dt2"; } 
} 

public interface IReadable 
{ 
    string Read(); 
} 

和执行的通用类型实现此接口:

public class Logger<T> where T : IReadable 

你必须去执行的Read操作实例的引用,然后你其实可以对记录仪本身就是一种委托Read动作:

public class Logger<T> where T : IReadable 
{ 
    private readonly T _readable; 

    public Logger<T>(T readable) 
    { 
     this._readable = readable; 
    } 

    public string Read() 
    { 
     return this._readable.Read(); 
    } 
} 

和使用将是:

var dt1 = new DataType1(); 
var dt2 = new DataType2(); 
var logger1 = new Logger<DataType1>(dt1); 
var logger2 = new Logger(dt2); // can omit generic noise! 
Console.WriteLine(logger1.Read()); // "dt1" 
Console.WriteLine(logger2.Read()); // "dt2" 

如果你想避免创建实例,并将其传递到记录器,你可以初始化它里面记录器,但你必须添加new()约束,这意味着有公共构造函数没有参数,你甚至可以有记录器实现IReadable本身:

public class Logger<T> : IReadable where T : IReadable, new() 
{ 
    private readonly T _readable; 

    public Logger<T>() 
    { 
     this._readable = new T(); 
    } 

    public string Read() 
    { 
     return this._readable.Read(); 
    } 
} 

而且用法是:

var logger1 = new Logger<DataType1>(); 
Console.WriteLine(logger1.Read()); // "dt1" 
+0

谢谢,经过一番深夜和期限,我觉得更容易问,因为我的大脑刚刚死了... :) – a11smiles 2015-02-11 16:16:56

4

使用的接口:

public interface IDataType 
{ 
    string Read(); 
} 

public class DataType1 : IDataType 
{ 
    public DataType1() { } 

    public string Read() { return "dt1"; } 
} 

public class DataType2 : IDataType 
{ 
    public DataType2() { } 

    public string Read() { return "dt2"; } 
} 

public class Logger<T> where T : IDataType, new() 
{ 
    IDataType dataType { get; set; } 

    public Logger() { 
     dataType = new T(); 
    } 

    public string Read() 
    { 
     return dataType.Read(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test1 = new Logger<DataType1>(); 
     test1.Read(); // I want this to equal "dt1"; 

     var test2 = new Logger<DataType2>(); 
     test2.Read(); // I want this to equal "dt2"; 
    } 
} 

顺便说一句,我认为更好的做法是放弃仿制药:

public interface IDataType 
{ 
    string Read(); 
} 

public class DataType1 : IDataType 
{ 
    public DataType1() { } 

    public string Read() { return "dt1"; } 
} 

public class DataType2 : IDataType 
{ 
    public DataType2() { } 

    public string Read() { return "dt2"; } 
} 

public class Logger 
{ 
    IDataType dataType { get; set; } 

    public Logger(IDataType dt) { 
     dataType = dt; 
    } 
    public string Read() 
    { 
     return dataType.Read(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var dt1 = new DataType1(); 
     var test1 = new Logger(dt1); 
     test1.Read(); // I want this to equal "dt1"; 

     var dt2 = new DataType2(); 
     var test2 = new Logger(dt2); 
     test2.Read(); // I want this to equal "dt2"; 
    } 
} 
0

正如@leppie说,如果你想补充的约束通用工具类声明。它可以解决这个问题。您需要通过构造函数或使用属性注入Logger类的依赖项。

比方说,比如你有以下接口:

public interface IReader 
{ 
    public String Read(); 
} 

,我们将有DataType1和DataType2看起来像

public class DataType1:IReader 
{ 
    public String Read() 
    { 
     return "dt1"; 
    } 
} 

你的工具类就可以变成类似:

public class Logger<T> where T:IReader 
{ 
    private T dataTypeInstance; 

    public Logger(T dataTypeInstance) 
    { 
     this.dataTypeInstance = dataTypeInstance; 
    } 

    public String Read() 
    { 
     return dataTypeInstance.Read(); 

    } 
} 

它的Read方法将简单地调用数据的Read方法类型类。

然后,我们可以从某种工厂 和试验获得DataType1和DataType2的情况下,用这样的:通过一个构造

var test1 = new Logger<DataType1>(dataType1); 
var test2 = new Logger<DataType2>(dataType2); 

test1.Read(); //will be dt1 
test2.Read(); //will be dt2 

或者代替使用依赖注入或属性在工具类,你可以使用反射和属性文件或(数据库存储的配置)以及is运算符来获取要使用的正确数据类型的实例。

0

如果你不能使用的界面,尽量使用lambda exprestion:

public class Logger<T> where T : new() 
{ 
    private Func<T, string> _readFunc; 
    private T _member; 

    public Logger(Func<T, string> readFunc) 
    { 
     _readFunc = readFunc; 
     _member = new T(); 
    } 

    // Use this if you already have an instance of your data type 
    public Logger(Func<T, string> readFunc, T member) 
    { 
     _readFunc = readFunc; 
     _member = member; 
    } 

    public string Read() 
    { 
     return _readFunc(_member); 
    } 
} 

,然后在您的应用程序:

static void Main() 
{ 
    var test1 = new Logger<DataType1>(t => t.Read()); 
    test1.Read(); // Will be equal "dt1"; 

    var test2 = new Logger<DataType2>(t => t.Read()); 
    test2.Read(); // Will be equal "dt2"; 
}