簡體   English   中英

配置如何解決ClientContext

[英]Configure how ClientContext is resolved

我正在一個項目中,我們正在使用存儲庫模式對對SharePoint存儲的數據的訪問進行抽象,如下所示(為簡便起見,省略了詳細信息):

    public interface IDocumentRepository { ... }
    public class SharePointDocumentRepository: IDocumentRepository
    {
        public SharePointDocumentRepository(Microsoft.SharePoint.Client.ClientContext clientContext)
        {
            ...
        }
    }

因此,為了能夠在ASP.Net MVC應用程序中使用IDocumentRepository實例,請在UnityConfig.cs中對容器進行如下配置:

    ...
    container.RegisterType<IDocumentRepository, SharePointDocumentRepository>();
    ...

問題是,在運行時,出現以下異常:

ClientContext類型具有多個長度為1的構造函數。無法消除歧義。

為了解決此問題,我需要注冊ClientContext應該如何解析。 到目前為止,我已經嘗試了以下方法,但沒有成功:

  1. 配置構造函數的使用,該構造函數具有字符串參數
  2. 在需要ClientContext時將Unity配置為返回特定實例

因此,我的問題是:有沒有一種方法可以配置Unity來解析ClientContext,或者每當我獲得該接口的實例時,是否應該通過IDocumentRepository接口的屬性來注入它? 注意:第二種方法將使SharePoint存儲庫可以用在任何其他無法訪問HTTP上下文的組件中,因此它不是可取的。

備注:可以按以下步驟創建沒有DI的存儲庫實例:

    ...
    [SharePointContextFilter]
    public ActionResult Index()
    {
        SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
        using(var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            var documentRepository = new SharePointDocumentRepository(clientContext);
            ...
        }
        ...
        return View();
    }

請注意,從“ Apps for SharePoint”項目模板創建項目時,會自動生成SharePointContextFilterAttributeSharePointContextProviderSharePointContext

因此,您的控制器依賴於IDocumentRepository ,但是這種依賴關系需要基於某些上下文創建,這些上下文只能從其自身的控制器操作內部獲取。 正確?

如果是這種情況,則需要使用Factory

在您的情況下,您的工廠應如下所示:

public interface IDocumentRepositoryFactory
{
    IDocumentRepository Create(Context context);
}

public class SharePointDocumentRepositoryFactory : IDocumentRepositoryFactory
{
    public IDocumentRepository Create(Context context)
    {
        //Create the repository
        SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(....);
        using(var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            return new SharePointDocumentRepository(clientContext); 
        }
    }
}

請注意,這里我使用Context作為Create方法的輸入。 您應該用控制器需要的任何上下文替換它,以便能夠構建存儲庫(如果有)。

現在,更改控制器的構造函數以在構造函數中接受IDocumentRepositoryFactory並將其存儲在字段中。

並且不要忘記像這樣注冊工廠:

container.RegisterType<IDocumentRepositoryFactory, SharePointDocumentRepositoryFactory>();

然后在操作中,可以使用factory創建存儲庫,如下所示:

var repository = m_DocumentRepositoryFactory.Create(....);

其中m_DocumentRepositoryFactory是用於在構造函數中存儲工廠依賴項的字段的名稱。

更新:

由於ClientContext類是可拋棄的,因此在處置ClientContext之后返回SharePointDocumentRepository沒有意義。

我建議您改用隔離工廠。 像這樣:

public interface IDocumentRepositoryIsolationFactory
{
    void CreateAndUse(Context context, Action<IDocumentRepository> action);
}

public class SharePointDocumentRepositoryIsolationFactory : IDocumentRepositoryIsolationFactory
{
    public void CreateAndUse(Context context, Action<IDocumentRepository> action)
    {
        //Create the repository
        SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(....);
        using(var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            var repository = SharePointDocumentRepository(clientContext); 

            action(repository);
        }
    }
}

並在您的操作中像這樣使用它:

m_IsolationFactory.CreateAndUse(... , (repository) =>
{
    //repository is a IDocumentRepository, use it here

});

您可以像這樣將ClientContext的實例傳遞給構造函數:

var clientContext = new ClientContext();
container.RegisterInstance<ClientContext>("myContext", clientContext);

container.RegisterType<IDocumentRepository, SharePointDocumentRepository>(new InjectionConstructor(container.Resolve<ClientContext>("myContext")));

暫無
暫無

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

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