使用仿制药从字符串中解析收集名称

发布于 2025-01-21 15:30:55 字数 3257 浏览 0 评论 0原文

我在mongo db中有一些收藏:autocomplete.brands and autocomplete.makes

这些集合中的每个集合都基于具有name 属性:

public class AutocompleteEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; } = ObjectId.GenerateNewId().ToString();

    [BsonElement("Name")]
    public string Name { get; set; }

    [BsonElement("Culture")]
    public string Culture { get; set; }

    [BsonElement("Key")]
    public string Key { get; set; }
}

我想在每个集合中使用仿制药进行搜索,这就是我所拥有的。

使用存储库的高级服务:

public class AutocompleteHandler : IAutocompleteHandler
{
    private readonly IAutocompleteRepository<Brands> _brandsRepository;
    private readonly IAutocompleteRepository<Makes> _makesRepository;

    public AutocompleteHandler(
        IAutocompleteRepository<Brands> brandsRepository,
        IAutocompleteRepository<Makes> makesRepository
        )
    {
        _brandsRepository = brandsRepository;
        _makesRepository = makesRepository;
    }

    public async Task<ICollection<string>> SearchForBrand(string name, string culture)
    {
        return await _brandsRepository.Search(name, culture);
    }

    public async Task<ICollection<string>> SearchForMake(string name, string culture)
    {
        return await _makesRepository.Search(name, culture);
    }
}

为此,我为每个存储库类型定义了一个类:

public interface IAutocompleteCollection
{
}

public class Brands : IAutocompleteCollection
{
}

public class Makes : IAutocompleteCollection
{
}

以及通用存储库:

public class AutocompleteRepository<T> : IAutocompleteRepository<T> where T : IAutocompleteCollection
{
    private readonly IMongoCollection<AutocompleteEntity> _collection;

    public AutocompleteRepository(IMongoTenantResolver mongoResolver)
    {
        var name = typeof(T).Name;
        var collectionName = $"autocomplete.{char.ToLowerInvariant(name[0]) + name.Substring(1)}";

        _collection = mongoResolver
            .GetMongoDbInstance()
            .GetCollection<AutocompleteEntity>(collectionName);
    }

    public async Task<List<string>> Search(string name, string culture)
    {
        var filter = Builders<AutocompleteEntity>.Filter.Regex("Name", new BsonRegularExpression(name, "i"));
        filter &= Builders<AutocompleteEntity>.Filter.Eq("Culture", culture);
        var data = await _collection.FindAsync(filter);
        var items = await data.ToListAsync();
        return items.Select(i => i.Name).ToList();
    }
}

我的问题

我正在使用“空类>为了能够通过通用存储库中的名称解决集合:

var name = typeof(T).Name;
var collectionName = $"autocomplete.{char.ToLowerInvariant(name[0]) + name.Substring(1)}";

是否有一种更优雅的方法可以使用仿制药而不依赖空的类/接口,或者在我的情况下,这是使用仿制药的最佳方法吗?

Update1:

​​@RoberTharvey的答案之后,我添加了此信息。仿制用法对我很有用,因为我正在使用依赖项注入,因此我可以在startup.cs中使用此单位,

services.AddTransient(typeof(IAutocompleteRepository<>), typeof(AutocompleteRepository<>));

然后我可以添加许多其他自动完整类型,而无需单独注册它们启动。同样,由于使用DI,我不确定如何将枚举价值注入构造函数。

I have some collections in a mongo DB: autocomplete.brands and autocomplete.makes

Each of these collections have items based on the same pattern that have a Name property:

public class AutocompleteEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; } = ObjectId.GenerateNewId().ToString();

    [BsonElement("Name")]
    public string Name { get; set; }

    [BsonElement("Culture")]
    public string Culture { get; set; }

    [BsonElement("Key")]
    public string Key { get; set; }
}

I would like to use generics for searching in each of these collections, here is what I have.

The high-level service using repositories:

public class AutocompleteHandler : IAutocompleteHandler
{
    private readonly IAutocompleteRepository<Brands> _brandsRepository;
    private readonly IAutocompleteRepository<Makes> _makesRepository;

    public AutocompleteHandler(
        IAutocompleteRepository<Brands> brandsRepository,
        IAutocompleteRepository<Makes> makesRepository
        )
    {
        _brandsRepository = brandsRepository;
        _makesRepository = makesRepository;
    }

    public async Task<ICollection<string>> SearchForBrand(string name, string culture)
    {
        return await _brandsRepository.Search(name, culture);
    }

    public async Task<ICollection<string>> SearchForMake(string name, string culture)
    {
        return await _makesRepository.Search(name, culture);
    }
}

For this to work I defined a class for each repository type:

public interface IAutocompleteCollection
{
}

public class Brands : IAutocompleteCollection
{
}

public class Makes : IAutocompleteCollection
{
}

and the generic repository:

public class AutocompleteRepository<T> : IAutocompleteRepository<T> where T : IAutocompleteCollection
{
    private readonly IMongoCollection<AutocompleteEntity> _collection;

    public AutocompleteRepository(IMongoTenantResolver mongoResolver)
    {
        var name = typeof(T).Name;
        var collectionName = 
quot;autocomplete.{char.ToLowerInvariant(name[0]) + name.Substring(1)}";

        _collection = mongoResolver
            .GetMongoDbInstance()
            .GetCollection<AutocompleteEntity>(collectionName);
    }

    public async Task<List<string>> Search(string name, string culture)
    {
        var filter = Builders<AutocompleteEntity>.Filter.Regex("Name", new BsonRegularExpression(name, "i"));
        filter &= Builders<AutocompleteEntity>.Filter.Eq("Culture", culture);
        var data = await _collection.FindAsync(filter);
        var items = await data.ToListAsync();
        return items.Select(i => i.Name).ToList();
    }
}

My question

I am using the empty classes Brands and Makes in order to be able to resolve the collection by name in the generic repository:

var name = typeof(T).Name;
var collectionName = 
quot;autocomplete.{char.ToLowerInvariant(name[0]) + name.Substring(1)}";

Is there a more elegant way to use generics without relying on empty classes/interface or is that the best way to use generics in my case?

Update1 :

After @RobertHarvey 's answer, I am adding this information. Generics usage is useful to me because I am using Dependency Injection and thus I can have this one-liner in Startup.cs:

services.AddTransient(typeof(IAutocompleteRepository<>), typeof(AutocompleteRepository<>));

I can then add many other autocomplete types without the need to register them individually in the Startup. Also because of DI usage, I am not sure how I can inject an enum value into the constructor.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深爱成瘾 2025-01-28 15:30:55
public enum CollectionName
{
    Brands,
    Makes
}

// Constructor
public AutoCompleteRepository(IMongoTenantResolver resolver, CollectionName name)
{
    // Name of collection is name.ToString().  Preserves static type checking,
    // avoids empty classes and interfaces.
}
public enum CollectionName
{
    Brands,
    Makes
}

// Constructor
public AutoCompleteRepository(IMongoTenantResolver resolver, CollectionName name)
{
    // Name of collection is name.ToString().  Preserves static type checking,
    // avoids empty classes and interfaces.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文