문제

데이터베이스 액세스를위한 일부 규칙을 캡슐화하는 간단한 기본 클래스를 만들려고 노력했습니다. 일반적으로 ProductID를 기반으로 제품을 선택하기 위해 "Products_Retrive_Product"라는 SPROC을 만듭니다. 기본 클래스에서 "검색"메소드가 파생 클래스가 정의에서 공급되는 유형을 반환하기를 원합니다. 제네릭으로 달성하려는 것이 가능합니까?

public class MyBaseClass <T>
{
    private string _className;

    public MyBaseClass ()
    {
        _className = this.GetType().Name;
    }

    public virtual T Retrieve(int ID)
    {
        Database db = DatabaseFactory.CreateDatabase();
        DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", _className));
        db.AddInParameter(dbCommand, String.Format("@{0}ID", _className), DbType.Int32, ID);

        using (IDataReader dr = db.ExecuteReader(dbCommand))
        {
            if (dr.Read())
            {
                BOLoader.LoadDataToProps(this, dr);
            }
        }
        return (T)this;
    }
}
도움이 되었습니까?

해결책

나는 당신이 다음과 같은 일을하고 싶다고 생각합니다.

class MyBaseClass<T> where T : MyBaseClass<T>, new()
{
    public T Retrieve()
    {
        return new T();
    }
}

class Foo : MyBaseClass<Foo>
{
}

class Program
{
    public static void Main()
    {
        Foo f = new Foo();
        Foo f2 = f.Retrieve();
        Console.WriteLine(f2.ToString());
    }
}

이 프로그램을 실행하면 foo 유형 이름이 명령 줄에 인쇄됩니다. 분명히 이것은 고안된 예이지만 데이터베이스에서로드 할 때 더 유용한 일을 할 수 있습니다. MyBaseClass.Retrieve().

핵심은 클래스 자체의 인스턴스가되어야하는 T에 제약 조건을 추가하는 것입니다. 이렇게하면 서브 클래싱시 서브 클래스를 일반 유형으로 지정할 수 있습니다. MyBaseClass<T>.

이것이 좋은 생각인지 아닌지는 확실하지 않지만, 그것을 할 수있는 것처럼 보입니다.

다른 팁

확신하는. 당신의 예에서, 내가 foo 클래스를 검색 할 때 막대를 반환하기를 원한다면 (...).

public class Foo : MyBaseClass<Bar>{}

흠, 우리는 반사를 사용하여 클래스 이름을 얻습니다. Boloader는 의심 할 여지없이 반사를 사용하여 일부 특성을로드하고 있습니다. 왜 완전히 반성에 전념하지 않습니까?

Boloader는이 "Return Type"게임에 신경 쓰지 않습니다. 왜 우리는해야합니까?

public static class MyBaseClassExtender
{
    public static void Retrieve(this MyBaseClass entity, int ID)
    {
        string className = entity.GetType().Name;
        Database db = DatabaseFactory.CreateDatabase();
        DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", className));
        db.AddInParameter(dbCommand, String.Format("@{0}ID", className), DbType.Int32, ID);

        using (IDataReader dr = db.ExecuteReader(dbCommand))
        {
            if (dr.Read())
            {
                BOLoader.LoadDataToProps(this, dr);
            }
        }
    }
}

그럼 당신은 그냥 말합니다 :

Foo myFoo = new Foo();
myFoo.Retrieve(2);

아니요, 당신이 실제로 할 수 있어야하는 것은 클래스 정의에서 이와 같은 것이기 때문입니다.

public class MyBaseClass<T> : T

현재 제네릭으로는 불가능합니다.

당신이해야 할 일은 공장을 공장에서 생산하는 것과 분리하는 것입니다 (t를 구축하는 별도의 클래스가 필요합니다. 그런 다음 t, 확장 방법에서 작동하기 위해 도우미 방법을 제공해야합니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top