简体   繁体   中英

C# Dynamic return type

I've solved my problem

    public virtual T GenerateCommand()
    {
        Type typeParameterType = typeof(T);
        if (typeParameterType == typeof(SqlCommand))
        {
            //SqlCommand
        }
        else if (typeParameterType == typeof(MySqlCommand))
        {
            //MySqlCommand
        }

        return new T()
        {

        };
    }

I'm building a class that generates Queries/Commands, the class has the ability to generate various DbCommands (MsSqlServer & MySql) when the type of the database is defined in field of the class. How can I return the correct type?

I tried this:

public virtual DbCommand GenerateCommand()
{
    //.....
}

but I always need to convert the return value:

MySqlCommand s = this.GenerateCommand() as MySqlCommand;

I also tried this:

public virtual T GenerateCommand<T>()
{
    //.....
}

But it's not what I'm looking for because I cannot create an instance of DbCommand so I cannot return nothing.

Is there some way that T will be based on stored type on my class?

Edit: the using of generic class throw two exceptions at least:

    if (T is MySqlCommand)
    {
        return new MySqlCommand();
    }
    else
    {
        return new SqlCommand();
    }

'T' is a 'type parameter' but is used like a 'variable'

Cannot implicitly convert type 'MySql.Data.MySqlClient.MySqlCommand' to 'T'

(T)MySqlCommand()

also do not work

Edit 2: can I do something like that?

public virtual T GenerateCommand(SqlDatabaseKind dbKind)
{
    T = (dbKind == SqlDatabaseKind.MicrosoftSqlServer) ? SqlCommand :
        MySqlCommand;
}

You can have generic classes. It sounds like this is more what you are looking for. Then you can just return the type that the class was created as:

public class MyDatabaseClass<T> where T : DbCommand
{

    public virtual T GenerateCommand()
    {
        //.....
    }
}

I have used a generic constraint to make sure that the T is of type DbCommand, also.

You make 'GenerateCommand()' as a void, with two overloads: one, which receives an 'out MySqlCommand', and another which receives an 'out SqlCommand', and change the in the function.

void GenerateCommand(out MySqlCommand com)
{
.
.
.
}

void GenerateCommand(out SqlCommand com)
{
.
.
.
}

out: http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.71).aspx

If you want to move between database types, then your code should depend on abstraction (DbCommand, DbConnection, DbParameter etc) instead of concrete implementations (SqlConnection, SqlCommand). Otherwise you will have to change all database-related code when new database provider added. And you will duplicate all database-related code for every provider.

.Net already has abstract factory for creating all this database-related abstractions. It's called DbProviderFactory . And looks like it's what you are trying to implement:

public virtual DbCommand CreateCommand()
public virtual DbConnection CreateConnection()

.Net has some built-in provider-specific implementations of this factory (SqlClientFactory, OleDbFactory, OdbcFactory). Here you can find how to use DbProviderFactories. And here you can find DbProviderFactory for MySql.

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