C#-静态方法或在使用第三方库时创建新实例

C#-静态方法或在使用第三方库时创建新实例,c#,asp.net,.net,asp.net-mvc,asp.net-web-api,C#,Asp.net,.net,Asp.net Mvc,Asp.net Web Api,我有一个只实现第三方库的类——我可以告诉你这是真的 我想知道在使用这种库时,如何正确地使用它 以下是我如何使用的示例: 新实例 声明 public class MyClass{ private readonly string _jsonPath= ...; public readonly StorageClient Client; public MyClass() { var credential = G

我有一个只实现第三方库的类——我可以告诉你这是真的

我想知道在使用这种库时,如何正确地使用它

以下是我如何使用的示例:

新实例

声明

public class MyClass{
        private readonly string _jsonPath= ...;

        public readonly StorageClient Client;

        public MyClass()
        {
            var credential = GoogleCredential.FromFile(_jsonPath);
            Client = StorageClient.Create(credential);
        }

        public string Upload(/*my parameter*/)
        {
            Client.UploadObject(...);
            // etc
        }
}
public class MyClass{
        private static readonly string _jsonPath= ...;

        public static readonly StorageClient Client = StorageClient.Create(GoogleCredential.FromFile(_jsonPath));

        public static string Upload(/*my parameter*/)
        {
            Client.UploadObject(...);
            // etc
        }
}

用法

静态方法

声明

public class MyClass{
        private readonly string _jsonPath= ...;

        public readonly StorageClient Client;

        public MyClass()
        {
            var credential = GoogleCredential.FromFile(_jsonPath);
            Client = StorageClient.Create(credential);
        }

        public string Upload(/*my parameter*/)
        {
            Client.UploadObject(...);
            // etc
        }
}
public class MyClass{
        private static readonly string _jsonPath= ...;

        public static readonly StorageClient Client = StorageClient.Create(GoogleCredential.FromFile(_jsonPath));

        public static string Upload(/*my parameter*/)
        {
            Client.UploadObject(...);
            // etc
        }
}

用法


由于这些方法将非常频繁地并发调用,我想知道哪种用法更好,以及为什么要避免出现问题

据我所知,static不善于共享同一个类成员

但我认为每次需要使用时都要声明客户端是多余的

我想知道更多关于这两种方式的利弊

如有任何建议,将不胜感激

我的英语很基础,请不要介意


谢谢您的阅读。

您可以将静态类用于常用组件。但我建议您应该使用单例设计模式进行此过程。

您可以将静态类用于常用组件。但我建议您应该使用单例设计模式进行此过程。

我将使用您的第一种方法并将上载方法更改为异步,以便独立任务可以并发运行。使用第二种方法,可以有两个不同的线程以非线程安全的方式更改同一对象

这样做:

public class MyClass{

    private readonly string _jsonPath= ...;
    private readonly StorageClient _storageClient;

    public MyClass()
    {
        var credential = GoogleCredential.FromFile(_jsonPath);
        _storageClient = StorageClient.Create(credential);
    }

    public Task<string> UploadAsync(/*my parameter*/)
    {
        var imageObject = await _storageClient.UploadObjectAsync(...);
        // etc
    }
}
公共类MyClass{
私有只读字符串_jsonPath=。。。;
私有只读存储客户端_-StorageClient;
公共MyClass()
{
var credential=GoogleCredential.from文件(\u jsonPath);
_storageClient=storageClient.Create(凭证);
}
公共任务上传异步(/*我的参数*/)
{
var imageObject=wait_storageClient.UploadObjectAsync(…);
//等
}
}

我将使用您的第一种方法,将上载方法更改为异步,以便独立任务可以并发运行。使用第二种方法,可以有两个不同的线程以非线程安全的方式更改同一对象

这样做:

public class MyClass{

    private readonly string _jsonPath= ...;
    private readonly StorageClient _storageClient;

    public MyClass()
    {
        var credential = GoogleCredential.FromFile(_jsonPath);
        _storageClient = StorageClient.Create(credential);
    }

    public Task<string> UploadAsync(/*my parameter*/)
    {
        var imageObject = await _storageClient.UploadObjectAsync(...);
        // etc
    }
}
公共类MyClass{
私有只读字符串_jsonPath=。。。;
私有只读存储客户端_-StorageClient;
公共MyClass()
{
var-credential=GoogleCredential.FromFile(_jsonPath);
_storageClient=storageClient.Create(凭证);
}
公共任务上传异步(/*我的参数*/)
{
var imageObject=wait_storageClient.UploadObjectAsync(…);
//等
}
}

根据MyClass的要求,这有点难以回答。我的班级做什么?它需要一些设置吗?建筑?上载方法是否取决于实例状态

我通常喜欢注入外部依赖项,并将它们隐藏在接口后面。这样,我就创建了双重测试,如果愿意的话,可以很容易地更改依赖项。我倾向于不喜欢使用静态,除非它用于无状态实用程序类,如数学、字符串操作、扩展和其他无状态处理

对于需要状态的东西,我使用实例。如果我真的需要共享状态,我会使用单例,但如果可能的话,我会尽量避免使用它们

在您的情况下,我将创建一个IStorageProvider,实现一个GoogleCloudStorageProvider,并将IStorageProvider的依赖项放在MyClass上

public class MyClass {
    IStorageProvider Storage;
    public MyClass(IStorageProvider storage)
    {
        Storage = storage;
    }
    public async void Upload(Data data){
        await Storage.Save(data);
    }
}

public interface IStorageProvider{
    void Upload(Data data);
}

public class GoogleCloudStorage:IStorageProvider{
    private Credentials Creds;
    private GoogleCloudClient Client;
    public GoogleCloudStorage(Credentials creds)
    {
        Creds = creds;
        Client = new GoogleCloudClient();
    }

    private void Connect(){
        Client.Connect(Creds);
    }
    public async void Upload(Data data){
        if(!Client.Connected){
            Connect();
        }
        return await Client.Upload(data);
    }
}

我觉得这种方法有点灵活。

根据您的MyClass要求,这有点难以回答。我的班级做什么?它需要一些设置吗?建筑?上载方法是否取决于实例状态

我通常喜欢注入外部依赖项,并将它们隐藏在接口后面。这样,我就创建了双重测试,如果愿意的话,可以很容易地更改依赖项。我倾向于不喜欢使用静态,除非它用于无状态实用程序类,如数学、字符串操作、扩展和其他无状态处理

对于需要状态的东西,我使用实例。如果我真的需要共享状态,我会使用单例,但如果可能的话,我会尽量避免使用它们

在您的情况下,我将创建一个IStorageProvider,实现一个GoogleCloudStorageProvider,并将IStorageProvider的依赖项放在MyClass上

public class MyClass {
    IStorageProvider Storage;
    public MyClass(IStorageProvider storage)
    {
        Storage = storage;
    }
    public async void Upload(Data data){
        await Storage.Save(data);
    }
}

public interface IStorageProvider{
    void Upload(Data data);
}

public class GoogleCloudStorage:IStorageProvider{
    private Credentials Creds;
    private GoogleCloudClient Client;
    public GoogleCloudStorage(Credentials creds)
    {
        Creds = creds;
        Client = new GoogleCloudClient();
    }

    private void Connect(){
        Client.Connect(Creds);
    }
    public async void Upload(Data data){
        if(!Client.Connected){
            Connect();
        }
        return await Client.Upload(data);
    }
}

我觉得这种方法有点灵活。

我不知道这里的单例方法和静态方法有什么区别。哦,我知道两者的区别。我的意思是,在我的用法上,它们看起来没有区别。不过还是要谢谢你。我不知道这里的单例方法和静态方法有什么区别。哦,我知道两者的区别。我的意思是,在我的用法上,它们看起来没有区别。不过还是谢谢你,这是个好主意。但是我想知道,如果第三方库没有实现异步方法,该怎么办?我可以通过单个实例安全地使用它吗?@TerryWei您使用的是ASP.NET MVC,这意味着框架将始终为每个http请求实例化一个新的控制器实例。因此,从“MyClass”调用方法不是线程安全的。但是,如果您的库不提供异步方法,您可以将这些调用包装到任务中。这是一个好主意。但是我想知道,如果第三方库没有实现异步方法,该怎么办?我可以通过单个实例安全地使用它吗?@TerryWei您使用的是ASP.NET MVC,这意味着框架将始终为每个http请求实例化一个新的控制器实例。因此,从“MyClass”调用方法不是线程安全的。但是,如果您的库不提供异步方法,您可以将这些调用包装到任务中。明白了!MyClass只收集和转换google函数所需的数据。我已经为几个google服务创建了几个类。所以我认为它更像是静态方法,但我不知道使用GoogleSDK实例作为静态是否合适。明白了!MyClass只收集一个