I have a Data access library which I would like to return different data formats (XML, Json, DataTable). I was trying to use Generics to achieve this.
public interface IDBInteractor<T>
{
T ExecuteDSQuery(string myQuery)
}
public class DBInteractorDT : IDBInteractor<DataTable>
{
public DataTable ExecuteDSQuery(string myQuery)
{
return new DataTable();
}
}
public class DBInteractorJson : IDBInteractor<JsonString>
{
public JsonString ExecuteDSQuery(string myQuery)
{
return new JsonString();
}
}
I am having trouble invoking the correct method. Ideally I would to declare something like
SomeClass<DataTable> dt = new SomeClass<DataTable>();
SomeClass<JsonString> js = new SomeClass<JsonString>();
DataTable myDT = dt.ExecuteDSQuery(myQuery);
JsonString myJson = js.ExecuteDSQuery(myQuery);
I'm not sure how to declare SomeClass. I know I could do something like
public class SomeClass<T> where T : IDBInteractor <T>
{
public T ExecuteQuery(T dtobject, string myQuery)
{
return dtobject.ExecuteDSQuery(myQuery);
}
}
But I don't want to have to pass an object instance (dtobject) to each method call.
if your generic parameter has a parameterless constructor you can create a new Object T();
but you have to define that your T has to have a parameterless constructor use the generic constraint new() to force that:
public class SomeClass<T> where T : IDBInteractor <T> , new()
You could add the new() constraint to your class definition so your class becomes:
public class SomeClass<T> where T : IDBInteractor <T>, new()
{
public T ExecuteQuery(string myQuery)
{
return new T().ExecuteDSQuery(myQuery);
}
}
You can then do any set up in a public parameterless constructor.
Your SomeClass<T>
has an dependency on IDBInteractor<T>
. You could add a new()
constraint so you can create a instance in SomeClass<T>
whenever you need one.
But why don't use the power of depencency injection? Just accept a IDBInteractor<T>
as a parameter at the constructor of SomeClass<T>
?
public class SomeClass<T> where T : IDBInteractor <T>
{
private IDBInteractor<T> _interactor;
public SomeClass(IDBInteractor<T> interactor)
{
_interactor = interactor;
}
public T ExecuteQuery(string myQuery)
{
return _interactor.ExecuteDSQuery(myQuery);
}
}
http://www.theserverside.com/news/1321158/A-beginners-guide-to-Dependency-Injection
What exactly are you trying to do? This code works fine:
using System.Data;
namespace ConsoleApplication7
{
internal class Program
{
private static void Main(string[] args)
{
IDBInteractor<DataTable> dt = new SomeClass<DataTable>(new DBInteractorDT());
IDBInteractor<JsonString> js = new SomeClass<JsonString>(new DBInteractorJson());
/*
or you can write
IDBInteractor<DataTable> dt = new DBInteractorDT();
IDBInteractor<JsonString> js = new DBInteractorJson();
*/
DataTable myDT = dt.ExecuteDSQuery("");
JsonString myJson = js.ExecuteDSQuery("");
}
}
public interface IDBInteractor<T>
{
T ExecuteDSQuery(string myQuery);
}
public class DBInteractorDT : IDBInteractor<DataTable>
{
#region IDBInteractor<DataTable> Members
public DataTable ExecuteDSQuery(string myQuery)
{
return new DataTable();
}
#endregion
}
public class DBInteractorJson : IDBInteractor<JsonString>
{
#region IDBInteractor<JsonString> Members
public JsonString ExecuteDSQuery(string myQuery)
{
return new JsonString();
}
#endregion
}
public class SomeClass<T> : IDBInteractor<T>
{
private IDBInteractor<T> interactor;
public SomeClass(IDBInteractor<T> interactor)
{
this.interactor = interactor;
}
public T ExecuteDSQuery(string myQuery)
{
return interactor.ExecuteDSQuery(myQuery);
}
}
public class JsonString
{
}
}
I agree with fix_likes_coding. If you only want to create a class to execute a query you may look at extension methods instead. This may not fit well in the scheme of things but might help if you wanted to keep things simple.
public static class InteractorUtils
{
public static T ExecuteQuery(this IDBInteractor<T> interactor, string myQuery)
{
return interactor.ExecuteDSQuery(myQuery);
}
}
and you could use it like this:
IDBInteractor<DataTable> dt = new DBInteractorDT();
dt.ExecuteQuery("");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.