我如何注册一个通用的对象工厂? [英] How can I register a generic object factory?

查看:140
本文介绍了我如何注册一个通用的对象工厂?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下两类:

public class KeyedEntity<TEntity>
{
    internal KeyedEntity() { }

    public Identifier Key { get; set; }
    public TEntity Entity { get; set; }
}

public static class KeyedEntity
{
    public static KeyedEntity<TEntity> Create<TEntity>(Identifier key, TEntity entity)
    {
        return new KeyedEntity<TEntity>
        {
            Key = key,
            Entity = entity,
        };
    }
}

究其原因,构造函数是内部第二类存在是我要执行更多的高维护 KeyedEntity.Create(X,Y )语法,而不是新KeyedEntity&LT; T&GT; {键= X,实体= Y} 。 (请注意,类型推断与前者的语法。)

The reason the constructor is internal and the second class exists is I want to enforce the more highly-maintainable KeyedEntity.Create(x, y) syntax rather than new KeyedEntity<T>{ Key = x, Entity = y }. (Note that the type is inferred with the former syntax.)

我想告诉AutoFixture如何创建 KeyedEntity 的实例。但是,注册办法似乎只能允许一个单一类型的注册,而不是开放式泛型类型。

I want to tell AutoFixture how to create an instance of KeyedEntity. However, the Register method only seems to allow registration of a single type rather than an open generic type.

如何注册 KeyedEntity.Create&LT; TEntity&GT; 作为创建函数 KeyedEntity&LT; TEntity&GT;

How can I register KeyedEntity.Create<TEntity> as the creation function for KeyedEntity<TEntity>?

推荐答案

要支持你的开放式泛型类型,你可以写一个自定义的样本生成器的:

To support your open generic type, you can write a custom Specimen Builder:

public class KeyedEntityBuilder : ISpecimenBuilder
{
    private readonly static MethodInfo createMethod =
        typeof(KeyedEntity).GetMethod("Create");

    public object Create(object request, ISpecimenContext context)
    {
        var t = request as Type;
        if (t == null ||
            !t.IsGenericType ||
            t.GetGenericTypeDefinition() != typeof(KeyedEntity<>))
            return new NoSpecimen(request);

        var entityType = t.GetGenericArguments().Single();

        var key = context.Resolve(typeof(Identifier));
        var entity = context.Resolve(entityType);

        return createMethod
            .MakeGenericMethod(entityType)
            .Invoke(null, new[] { key, entity });
    }
}

(防御编码省略清晰。)

(Defensive coding omitted for clarity.)

下面的单元测试通过:

public class Tests
{
    [Fact]
    public void CreateKeyedEntity()
    {
        var fixture = new Fixture();
        fixture.ResidueCollectors.Add(new KeyedEntityBuilder());

        var actual = fixture.Create<KeyedEntity<Foo>>();

        Assert.NotNull(actual.Key);
        Assert.NotNull(actual.Entity);
    }
}

为了更好的可维护性,你应该封装 KeyedEntityBuilder 在自定义

For better maintainability, you should encapsulate KeyedEntityBuilder in a Customization.

这篇关于我如何注册一个通用的对象工厂?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆