簡體   English   中英

Ninject綁定通用接口

[英]Ninject Binding Generic Interfaces

我正在嘗試使用DI來綁定我的網絡類的其他實現。 我可以使用該類的非通用版本成功完成此操作。 我的實現如下:

class MainClass
{
    public static void Main(string[] args)
    {
        IKernel kernel;

        // Hardcode here but will be managed by build system.
        bool runningInProd = false;

        if (runningInProd)
        {
            kernel = new StandardKernel(new RealNetworkModule());
        }
        else
        {
            kernel = new StandardKernel(new FakeNetworkModule());
        }

        Session session = kernel.Get<Session>();

        session.Authenticate();
    }

    public class RealNetworkModule : NinjectModule
    {
        public override void Load()
        {
            Bind(typeof(IRequestSender)).To(typeof(RealRequestSender));
        }
    }

    public class FakeNetworkModule : NinjectModule
    {
        public override void Load()
        {
            Bind(typeof(IRequestSender)).To(typeof(FakeRequestSender));
        }
    }
}

使用我的IRequestSender的類:

public class Session
{
    IRequestSender requestSender;

    [Inject]
    public Session(IRequestSender requestSender)
    {
        this.requestSender = requestSender;
    }

    public void Authenticate()
    {
        Console.WriteLine(requestSender.Send("Hello There"));
    }
}

IRequestSender接口:

public interface IRequestSender
{
    string Send(string request);
}

以及兩種不同的實現:

public class RealRequestSender: IRequestSender
{
    public string Send(string request)
    {
        return "RealRequestSender right back at you: " + request;
    }
}

public class FakeRequestSender: IRequestSender
{
    public string Send(string request)
    {
        return "FakeRequestSender right back at you: " + request;
    }
}

這非常簡單並且有效。 但是,我需要IRequestSender使用通用類型而不是字符串作為輸入輸出:

public interface IRequestSender<RequestT, ResponseT> where RequestT: class where ResponseT: class
{
    RequestT Send(RequestT request);
}

而impl的:

public class FakeRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
    public RequestT Send(RequestT request)
    {
        throw new NotImplementedException();
    }
}

public class RealRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
    public RequestT Send(RequestT request)
    {
        throw new NotImplementedException();
    }
}

我遇到了幾個解決此問題的示例,但我嘗試將其實現作為基礎,但失敗了。 這是我遇到的兩個問題:

1)綁定:這是主要問題。 根據我在網上看到的解決方案,這是我的綁定外觀:

public class RealNetworkModule : NinjectModule
{
    public override void Load()
    {
        Bind(typeof(IRequestSender<>)).To(typeof(RealRequestSender<>));
    }
}

VSCode給我錯誤:

Program.cs(29,29): Error CS0305: Using the generic type 'IRequestSender<RequestT, ResponseT>' requires 2 type arguments (CS0305) (DI)

基於此錯誤以及我在網上閱讀的內容,我仍然不清楚在這里需要做什么。

2)訪問IRequestSender:一旦我知道如何解決綁定問題,解決方案就可能很清楚。 在原始實現中,我使用[Inject]來訪問Sessions類中所需的IRequestSender。 但是現在在通用版本中,我想我將無法執行此操作。 如果我要使用沒有DI的RequestSender,它將看起來像:

RequestSender <AuthRequest, AuthResponse> requestSender = new RequestSender<AuthRequest, AuthResponse>();

要么

RequestSender <UserRequest, UserResponse> requestSender = new RequestSender< UserRequest, UserResponse >();

適用於任何數量的不同類型。

因此,在這種情況下,我不確定如何去訪問RequestSender。

給定當前接口,在注入時必須指定通用類型參數。 假設您的請求和響應都是字符串,那么構造函數將如下所示:

public Session(IRequestSender<string, string> requestSender)
{
    this.requestSender = requestSender;
}

如果您不想在創建/注入時指定參數,則必須對設計進行一些更改。 我不能肯定使用您提供的示例代碼,但是可以從接口中刪除泛型類型args並將它們放在方法上:

public interface IRequestSender
{
    RequestT Send<RequestT, ResponseT>(RequestT request)
        where RequestT: class
        where ResponseT: class;
}

使用該定義,您將注入IRequestSender ,然后在調用時指定泛型類型參數。 例如,

string myResponse = requestSender.Send<string, string>("my string");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM