[英]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應該如何解析。 到目前為止,我已經嘗試了以下方法,但沒有成功:
因此,我的問題是:有沒有一種方法可以配置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”項目模板創建項目時,會自動生成SharePointContextFilterAttribute
, SharePointContextProvider
和SharePointContext
。
因此,您的控制器依賴於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.