c # Generics: diferentes tipos de devoluciones usando genéricos

Tengo una biblioteca de acceso a datos que me gustaría devolver diferentes formatos de datos (XML, Json, DataTable). Estaba tratando de usar Generics para lograr esto.

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

Tengo problemas para invocar el método correcto. Idealmente, declararía algo como

     SomeClass<DataTable> dt = new SomeClass<DataTable>();
     SomeClass<JsonString> js = new SomeClass<JsonString>();

     DataTable myDT = dt.ExecuteDSQuery(myQuery);
     JsonString myJson = js.ExecuteDSQuery(myQuery);

No estoy seguro de cómo declarar SomeClass. Sé que podría hacer algo como

    public class SomeClass<T> where T : IDBInteractor <T>
    {
        public T ExecuteQuery(T dtobject, string myQuery)
        {
           return dtobject.ExecuteDSQuery(myQuery);
        }
    }

Pero no quiero tener que pasar una instancia de objeto (dtobject) a cada llamada de método.

preguntado el 08 de noviembre de 11 a las 10:11

Por qué DBInteractorJson's ExecuteDSQuery devuelve cadena? Debería volver JsonString -

Comparación SomeClass<DataTable> dt = new SomeClass<DataTable>(); y public class SomeClass<T> where T : IDBInteractor <T>. Sin embargo, DataTable no es un IDBInteractor <T> -

5 Respuestas

si su parámetro genérico tiene un constructor sin parámetros, puede crear un nuevo Objeto T ();

pero tienes que definir que tu T tiene que tener un constructor sin parámetros que use la restricción genérica new () para forzar eso:

public class SomeClass<T> where T : IDBInteractor <T> , new()

respondido 08 nov., 11:14

Puede agregar la restricción new () a la definición de su clase para que su clase se convierta en:

public class SomeClass<T> where T : IDBInteractor <T>, new()
{
    public T ExecuteQuery(string myQuery)
    {
       return new T().ExecuteDSQuery(myQuery);
    }
}

A continuación, puede realizar cualquier configuración en un constructor público sin parámetros.

respondido 08 nov., 11:14

Sus SomeClass<T> tiene una dependencia de IDBInteractor<T>. Podrías agregar un new() restricción para que pueda crear una instancia en SomeClass<T> siempre que lo necesite.

Pero, ¿por qué no utilizar el poder de la inyección de dependencia? Solo acepta un IDBInteractor<T> como parámetro en el constructor de SomeClass<T>?

El código

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);
    }
}

Véase también

http://www.theserverside.com/news/1321158/A-beginners-guide-to-Dependency-Injection

respondido 08 nov., 11:14

Estoy de acuerdo con fix_likes_coding. Si solo desea crear una clase para ejecutar una consulta, puede buscar métodos de extensión en su lugar. Es posible que esto no encaje bien en el esquema de las cosas, pero podría ayudar si desea mantener las cosas simples.

public static class InteractorUtils
{
    public static T ExecuteQuery(this IDBInteractor<T> interactor, string myQuery)
    {
        return interactor.ExecuteDSQuery(myQuery);
    }
}

y podrías usarlo así:

IDBInteractor<DataTable> dt = new DBInteractorDT();

dt.ExecuteQuery("");

respondido 08 nov., 11:15

¿Qué estás tratando de hacer exactamente? Este código funciona bien:

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
    {
    }
}

respondido 08 nov., 11:15

Tienes razón, originalmente estaba invocando por error el objeto como: DBInteractorDT dt = nuevo DBInteractorDT (); - keitn

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.