简体   繁体   中英

The type cannot be used as type parameter in the generic type or method

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 TestOne ResultItem. But, I am unable to make this work with the where clause. Alternatively, directly creating TestTwo ResultItem [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!
    }
}

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()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM