Reputation: 1284
I have a DBHelper class from which I fire callbacks to convert IDataReader to a Generic Type. I have got the entire code up and running. However, I run into trouble when I attempt to create an instance of the type within the callback, with the where clause applied [See -> DataReaderToResultItemConverterCallback in class TestOneCallbacks].
The where clause makes it perfect. TResult will be type TestOneResultItem. But, I am unable to make this work with the where clause. Alternatively, directly creating TestTwoResultItem [See -> class TestTwoCallbacks] and casting makes it work, but not elegant.
This is the following Error for TestOneCallbacks,
The type 'TResult' cannot be used as type parameter 'TResult' in the generic type or method 'DataAccess.TestOneCallbacks.DataReaderToResultItemConverterCallback(System.Data.IDataReader)'. There is no boxing conversion or type parameter conversion from 'TResult' to 'Service.Interface.TestFilterResultItem'.
Here is the code.
public static class DBHelper
{
public static List<TResult> ExecuteQuery<TResult>(DataQueryArgs<TResult> dataQueryArgs)
{
List<TResult> result = null;
{
IDataReader reader = null;
//Get the input parameters for the query
Dictionary<string, object> inputParameters = dataQueryArgs.InputParameters;
//Fire callback to Get the DbCommand for the query
DbCommand command = dataQueryArgs.GetCommandCallback();
//Fire callback to Get the list of Sql input Parameters for the query
List<SqlParameter> sqlParameters = dataQueryArgs.CreateSQLParametersCallback(inputParameters);
//Execute the query and get an IDataReader object
reader = ExecuteQuery(command, sqlParameters);
//Fire callback Convert the IReader to ResultItem
result = dataQueryArgs.DataReaderToResultItemConverterCallback(reader);
}
return result;
}
private static IDataReader ExecuteQuery(DbCommand command, List<SqlParameter> sqlParameters)
{
IDataReader reader = null;
{
//TODO:
}
return reader;
}
}
class TestOneResultItem
{
public TestOneResultItem()
{
}
public string Name { get; set; }
public int Age { get; set; }
public DateTime DOB { get; set; }
}
class TestTwoResultItem
{
public TestTwoResultItem()
{
}
public string Description { get; set; }
public int Size { get; set; }
}
public class TestOneCallbacks
{
public DataQueryArgs<TResult> InitializeDataQueryCallbacks<TResult>(Dictionary<string, object> dataQueryArgs_inputParameters)
{
DataQueryArgs<TResult> args = null;
DataQueryArgs<TResult>.DataReaderToResultItemConverter<TResult> dataReaderToResultItemConverterCallback = this.DataReaderToResultItemConverterCallback<TResult>;
args = new DataQueryArgs<TResult>(dataReaderToResultItemConverterCallback);
return args;
}
public List<TResult> DataReaderToResultItemConverterCallback<TResult>(IDataReader reader) where TResult : TestOneResultItem
{
List<TResult> results = new List<TResult>();
TResult t1 = new TResult(); //Activator.CreateInstance ???
{
t1.Name = "ShaQ";
t1.Age = 99;
t1.DOB = DateTime.Now;
}
results.Add(t1);
return results;
}
}
public class TestTwoCallbacks
{
public DataQueryArgs<TResult> InitializeDataQueryCallbacks<TResult>(Dictionary<string, object> dataQueryArgs_inputParameters)
{
DataQueryArgs<TResult> args = null;
DataQueryArgs<TResult>.DataReaderToResultItemConverter<TResult> dataReaderToResultItemConverterCallback = this.DataReaderToResultItemConverterCallback<TResult>;
args = new DataQueryArgs<TResult>(dataReaderToResultItemConverterCallback);
return args;
}
public List<TResult> DataReaderToResultItemConverterCallback<TResult>(IDataReader reader) where TResult : TestTwoResultItem
{
var results = new List<TestTwoResultItem>();
TestTwoResultItem t1 = new TestTwoResultItem(); //Activator.CreateInstance ???
{
t1.Description = "This works...";
t1.Size = 345;
}
results.Add(t1);
return results as List<TestTwoResultItem>; //Ugly, but I know exactly what I am doing. This cast will succeed!
}
}
Upvotes: 0
Views: 2855
Reputation: 156918
If you are passing TResult
to that method, the TResult
you derive from the calling method should have the same type constraint as the called method. So you have to add the type constraint where TResult : TestOneResultItem
to the calling method: InitializeDataQueryCallbacks
.
public DataQueryArgs<TResult> InitializeDataQueryCallbacks<TResult>
(Dictionary<string, object> dataQueryArgs_inputParameters)
where TResult : TestOneResultItem
And by the way, in order to call the TResult
constructor, you need the new()
constraint:
where TResult : TestOneResultItem, new()
Upvotes: 4