Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Castle.DynamicProxy.ProxyGenerationException: Duplicate element: Castle.DynamicProxy.Generators.MetaMethod #596

Closed
TheReaLee opened this issue Aug 31, 2021 · 4 comments

Comments

@TheReaLee
Copy link

TheReaLee commented Aug 31, 2021

Same class names, in different projects both implementing the same interface with different namespaces. When using Mock.Object, the exception is thrown.

Castle.Core: 4.4.1
Moq: 4.16.1
.NETFramework: 4.7.2

TestClass

public class ReportInstanceBackwardCompatibilityTests
{
    private readonly ReportInstanceRepositoryIntegrationTestsFixture _fixture;

    public ReportInstanceBackwardCompatibilityTests(ReportInstanceRepositoryIntegrationTestsFixture fixture)
    {
        this._fixture = fixture;
        this._fixture.ConfigureDataStores(new MyDataStoreCollection())
    }

    [Fact]

    public void Test1()
    {
        /* On run of this test, the error should generate */
    }
}

MyDataStoreCollection

public class MyDataStoreCollection: IDataStoreCollection
{
    protected readonly Mock<IValidator<It.IsAnyType>> ValidatorMock;

    public MyDataStoreCollection()
    {
	this.ValidatorMock = new Mock<IValidator<It.IsAnyType>>();
    }

    public void RegisterValidator<TEntity>() 
    	where TEntity: new()
    {            
        this.ValidatorMock.As<IValidator<TEntity>>().Setup(x => x.Validate(It.IsAny<TEntity>(), It.IsAny<System.ComponentModel.DataAnnotations.ValidationContext>())).Returns(new ValidationResults());
    }

    /* Exception on .Returns(this.ValidatorMock.Object); */
    public IValidatorFactory GetValidatorFactory()
    {
	Mock<IValidatorFactory> validatorFactoryMock = new Mock<IValidatorFactory>();            
	validatorFactoryMock.Setup(x => x.CreateValidator<It.IsAnyType>(It.IsAny<IUnitOfWork>())).Returns(this.ValidatorMock.Object);

	return validatorFactoryMock.Object;
    }
}

TestFixture

public class MyFixture
{
    public void ConfigureDataStores(IDataStoreCollection dataStoreCollection)
    {
    	/* ReportingSchema.Reporting.Database.Model.ReportInstance is contained in project named 'Reporting'
	 * ReportInstance is contained in project named 'ReportingTenant'
	 * both implementing same interface
    	 */
        dataStoreCollection.RegisterValidator<ReportingSchema.Reporting.Database.Model.ReportInstance>();
        dataStoreCollection.RegisterValidator<ReportInstance>();     
        
        /* Exception when calling this method... */
        dataStoreCollection.GetValidatorFactory();
    }
}

IValidatorFactory

public interface IValidatorFactory
{
    IValidator<TModel> CreateValidator<TModel>(IUnitOfWork uow);
    IValidator<TModel> CreateValidator<TModel>();
    IValidator CreateValidator(Type modelType);
}

IValidator

public interface IValidator<TModel>
{    
    ValidationResults Validate(TModel instance);
}

ValidationResults taken from Nuget Microsoft.Practices.EnterpriseLibrary.Validation

IDataStoreCollection

public interface IDataStoreCollection
{   
    void RegisterDataStore<TEntity>() where TEntity : new();
  
    void RegisterDataStore<TEntity, TDataStore>()
        where TEntity : new()
        where TDataStore : IDataStore<TEntity>;
        
    IValidatorFactory GetValidatorFactory();
}

IDataStore

public interface IDataStore<TEntity>
{
    TEntity Insert(TEntity pModel);
}

IReportInstance

public interface IReportInstance
{       
	Guid Id { get; set; }
}

ReportingSchema ReportInstance (In project Reporting.csproj)

[Entity(Schema = "Reporting", Name = "Report_Instance", TableName = "Report_Instance")]
[EntitySecurity(ImplementsRecordSecurity = true)]
public class ReportInstance : IReportInstance
{
    [Key]
    [Index(IsUnique = true)]
    [Column(Order = 1)]
    public Guid Id {get;set;}
}

ReportingTenant schema ReportInstance (IN project ReportingTenant.csproj

[Entity(Schema = "ReportingTenant", Name = "Report_Instance", TableName = "Report_Instance")]
[EntitySecurity(ImplementsRecordSecurity = true)]
public class ReportInstance :  IReportInstance
{
    [Key]
    [Index(IsUnique = true)]
    [Column(Order = 1)]
    public Guid Id {get;set;}
}

IUnitOfWork

public interface IUnitOfWork
{
    IDataContext GetDataContext(Type type);      
}

IDataContext

public interface IDataContext : IDisposable
{
    bool InTransaction { get; }
    Task<int> CommitAsync();
}

Stack Trace

   at Castle.DynamicProxy.Generators.TypeElementCollection`1.Add(TElement item)
   at Castle.DynamicProxy.Contributors.CompositeTypeContributor.CollectElementsToProxy(IProxyGenerationHook hook, MetaType model)
   at Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.<>c__DisplayClass6_0.<GenerateCode>b__0(String n, INamingScope s)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass34_0.<ObtainProxyType>b__0(CacheKey _)
   at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
   at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
   at Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
   at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments) in C:\projects\moq4\src\Moq\ProxyFactories\CastleProxyFactory.cs:line 50
   at Moq.Mock`1.InitializeInstance() in C:\projects\moq4\src\Moq\Mock`1.cs:line 309
   at Moq.Mock`1.OnGetObject() in C:\projects\moq4\src\Moq\Mock`1.cs:line 325
   at Moq.Mock`1.get_Object() in C:\projects\moq4\src\Moq\Mock`1.cs:line 283
@stakx
Copy link
Member

stakx commented Aug 31, 2021

Hi @TheReaLee (sorry, I accidentally hit the Close issue button), could you please provide a full repro, i.e. not just the code where the exception is reported, but also include the declarations for the referenced types. Thanks!

@stakx stakx closed this as completed Aug 31, 2021
@stakx stakx reopened this Aug 31, 2021
@TheReaLee
Copy link
Author

Updated @stakx, let me know if you require more information

@stakx
Copy link
Member

stakx commented Dec 29, 2022

Sorry @TheReaLee, I cannot piece together repro code that compiles without error.

  • Some of the types you're referencing are missing: e.g. IValidator and ReportInstanceRepositoryIntegrationTestsFixture.
  • You're referencing custom attributes from some unspecified namespace or NuGet package: e.g. [Entity], [EntitySchema], [Key], [Index], and [Column].
  • There is at least one obvious Moq usage error: Mock<IValidator<It.IsAnyType>>. It.IsAnyType can only act as a type placeholder inside setup or verification expressions. It doesn't make any sense to use it outside of those expressions. (Because your own class and interface types aren't subtypes of It.IsAnyType – at least they shouldn't be! – there will not ever be any object at runtime that is assignment-compatible with It.IsAnyType, so your IValidator<It.IsAnyType> won't ever receive any It.IsAnyType-typed object to validate. Such a validator (whether mocked or not) is therefore completely useless in practice. Mock<IValidator<object>> would seem to make more sense.)

Could you perhaps provide a downloadable & compilable Visual Studio solution that doesn't need any further puzzle action on our part? :-)

@stakx
Copy link
Member

stakx commented Aug 28, 2023

I've re-tried producing the reported error using a variety of type proxying constellations, without any success. Closing this older issue as not reproducible.

@stakx stakx closed this as completed Aug 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants