如何在单独的 class 库中管理客户端上下文对象?

How to manage client context object in seperate class library?

我正在尝试为 sharepoint 创建一个 库(class 库),它将所有 sharepoint dll 与 sharepoint 服务器交互以 上传文件、文档并创建文档库和文档集

现在这个库可以被 客户端使用,例如 Web 应用程序(asp.net webform 或 mvc)或控制台应用程序或 Web api/wcf 服务或 windows 表单 随便什么。

所以在这里我对创建存储库模式和工作单元层以管理客户端上下文对象有点困惑。

我不确定是否允许为每个操作创建客户端上下文,或者是否创建一次客户端上下文并重复使用,或者是否每次都创建客户端上下文。

我进行了很多搜索,但找不到任何参考或文章来创建存储库层,就像它在 Entity framework DbContext 的情况下创建的那样。

我正在使用客户端对象模型(CSOM 库),我的库完全是关于内容管理系统来管理文件和元数据.

我将不胜感激:)

更新: 在 Sharepoint 域上上传文件的示例代码

ClientContext context = new ClientContext("http://SiteUrl"); // Starting with ClientContext, the constructor requires a URL to the server running SharePoint. 
context.Credentials = new SharePointOnlineCredentials(username, password);

// The SharePoint web at the URL.
Web myWeb = context.Web;

List myLibrary = myWeb.Lists.GetByTitle("MyProject"); //This is called document library so in sharepoint document Library is the root where we can create
                                                       //Document Set(Advance version of folder) or folder(Simple Folder) or upload files directly inside document library

FileCreationInformation info = new FileCreationInformation();
info.Url = "Sample.txt";
info.Overwrite = true;
info.Content = System.IO.File.ReadAllBytes("C://sample.txt"); //This will be user uploaded file that will be dynamic
myLibrary.RootFolder.Files.Add(info);
context.ExecuteQuery(); // Execute the query to the server.This is like EF SaveChanges method

一些参考资料: https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff649690(v=pandp.10)

https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-client-library-code

https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ee538685%28v%3doffice.14%29

https://sharepoint.stackexchange.com/questions/96180/sharepoint-2013-csom-is-it-better-to-pass-a-context-object-around-or-a-url

我认为您需要在如下所示的 WCF 服务中创建一个身份验证服务,它将处理所有登录的用户每当有任何新请求进入您以获取该用户的详细信息(无论是否为真实用户)时然后相应地执行

    [ServiceContract]
    public interface IAuthenticationService
    {
       [OperationContract]
       ClientInfo ChangeSessionUser(User user);
       [OperationContract]
       ClientInfo GetSessionUserInfo();
       [FaultContract(typeof(ServiceFault))]
       [OperationContract]
       ClientInfo Login(LoginCredentials credentials);
       [OperationContract]
       void Logout(string id);
       [FaultContract(typeof(ServiceFault))]
       [OperationContract]
       void RemoveInvalidUserLogins();
       [OperationContract]
       void RemoveSesseionFromCache(string id);
       [FaultContract(typeof(ServiceFault))]
       [OperationContract]
       bool ValidateUser(LoginCredentials credentials);
    }

关于您的第一个问题:

I am not sure whether to allow creation of client context for each operation or whether to create client context once and reuse or whether to create clientcontext each time.

为什么不让使用您的库的开发人员选择?即,您提供上下文,他们可以对其进行初始化并将其保留在他们需要的范围内。

例如,如果您的库用于网站,他们可能希望在每次请求时对其进行初始化,但如果您的库用于桌面应用程序,他们可能希望每次 window.

关于您的第二期:

I have search a lot but was unable to find any reference or article to create repository layer like the way it is created in case of Entity framework DbContext.

存储库和工作单元模式只是可以应用于任何上下文的抽象层。存储库将为给定对象或实体实施一组相关操作,而工作单元将为给定上下文(数据库事务等)中的一个或多个实体实施一组相关操作。

恕我直言,存储库对于您尝试做的事情没有多大意义,但是您可以实现一个包装 ClientContext 实例的工作单元。

首先,从一个接口开始,定义您将公开的方法,例如:

public interface IContentManagerUnitOfWork
{
    IEnumerable<List> GetLists();
    List CreateList(ListCreationInformation listCreationInformation);
    List GetListByTitle(string title);
    [...]
}

然后你实现它,这里是一个想法:

public class ContentManagerUnitOfWork : IContentManagerUnitOfWork, IDisposable
{
    private ClientContext clientContext;
    private Web web;

    public ContentManagerUnitOfWork(string url, username, password)
    {
        clientContext = new ClientContext(url);
        clientContext .Credentials = new SharePointOnlineCredentials(username, password);

        web = context.Web;
    }

    public IEnumerable<List> GetLists()
    {
        clientContext.Load(web.Lists);
        clientContext.ExecuteQuery(); 
        return web.Lists;
    }

    List CreateList(ListCreationInformation listCreationInformation)
    {
        List list = web.Lists.Add(listCreationInformation); 
        list.Update(); 
        clientContext.ExecuteQuery(); 
        return list;
    }

    List GetListByTitle(string title)
    {
        return web.Lists.GetByTitle("Announcements"); 
    }

    public void Dispose()
    {
        clientContext.Dispose();
    }
}

然后,任何使用您的库的开发人员都可以简单地使用工作单元和您提供的方法:

using (var unitOfWork = new ContentManagerUnitOfWork("http://SiteUrl", username, password))
{
     var lists = unitOfWork.GetLists();
}

当然,这只是一个不同的基本示例,您应该根据自己的需要对其进行调整,并确保它是与 Sharepoint 交互的正确方式。不过,我希望它能让你继续前进。