Calling a base class method using Reflection.Emit

I have set up my code to define the type, set the parent type, and also implement the interface. The problem I'm running into is that when I go to create a type, it says it can't find method implementations for the interface, even though those methods are implemented in the parent type. From what I've seen you need to define methods to get through a situation like this, here's my code:

    public interface IService<TDto, TId>
{
    Task<TId> CreateAsync(TDto entity);
    Task<bool> DeleteAsync(TId id);
    Task<bool> UpdateAsync(TDto entity);
    Task<List<TDto>> GetAllAsync();
    Task<TDto> GetAsync(TId id);
    TDto Get(TId id);
    Task<IEnumerable<TDto>> GetAllPagedAsync(Int32 page, Int32 take);
    Task<Int32> GetCountAsync();
    Task<object> GetForIdsAsync(TId[] ids, Int32? page = null, Int32? pageSize = null);
    object GetForIds(TId[] ids, Int32? page = null, Int32? pageSize = null);
    Task<bool> DeleteForIdsAsync(TId[] ids);
    Task<List<TDto>> CloneEntitiesAsync(List<TDto> dtos);
    Task<IList> GetForTypesAndIdsAsync(List<string> types, List<object[]> typeIds);
    Task<object> GetByConditionsAsync(Query query);
    Task<object> ExceptIdsAsync(TId[] ids, Int32? page = null, Int32? pageSize = null);
    bool Merge(TDto dto);
}

public Type[] CreateServiceType(Type dtoType, Type entityType, ModuleBuilder moduleBuilder)
        {
            string namespaceName = string.Format("Services.{0}", ProfileNamePlural);

            TypeBuilder iserviceTypeBuilder =
                moduleBuilder.DefineType(
                string.Format("{0}.I{1}Service", namespaceName, ClassName), 
                TypeAttributes.Interface | TypeAttributes.Abstract);

            var baseIServiceType = typeof (IService<,>).MakeGenericType(dtoType, entityType);
            iserviceTypeBuilder.AddInterfaceImplementation(baseIServiceType);

            Type iserviceType = iserviceTypeBuilder.CreateType();

            var baseType = typeof(AService<,,>).MakeGenericType(dtoType, entityType, typeof(Guid));

            string serviceClassName = string.Format("{0}.{1}Service", namespaceName, ClassName);

            TypeBuilder serviceTypeBuilder =
                moduleBuilder.DefineType(serviceClassName, TypeAttributes.Public);

            serviceTypeBuilder.SetParent(baseType);

            serviceTypeBuilder
                .AddInterfaceImplementation(iserviceType);

            var repositoryType = typeof(IRepository<>).MakeGenericType(entityType);

            ConstructorBuilder ctorBuilder =
                serviceTypeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    new[] { repositoryType });

            var baseConstructor =
                baseType.GetConstructor(
                BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance,
                    null, 
                    new[] { repositoryType }, 
                    null);

            var ilGenerator = ctorBuilder.GetILGenerator();

            // Generate constructor code
            ilGenerator.Emit(OpCodes.Ldarg_0);                // push "this" onto stack. 
            ilGenerator.Emit(OpCodes.Ldarg_1);
            ilGenerator.Emit(OpCodes.Call, baseConstructor);
            ilGenerator.Emit(OpCodes.Ret);

            DefinePassThroughs(ref serviceTypeBuilder, baseType, baseIServiceType);

            return new[] { serviceTypeBuilder.CreateType(), iserviceType };
        }

private void DefinePassThroughs(ref TypeBuilder typeBuilder, Type baseType, Type iServiceType)
        {
            var virtualMethods = iServiceType.GetMethods();
            foreach (var imethod in virtualMethods)
            {
                var method = baseType.GetMethod(imethod.Name);
                var paramTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();

                var passThroughMethod =
                    typeBuilder.DefineMethod(
                    method.Name, 
                    MethodAttributes.Public, 
                    CallingConventions.Standard,
                    method.ReturnType,
                    paramTypes);

                var il = passThroughMethod.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                for (var i = 0; i < paramTypes.Length; i++)
                {
                   il.Emit(OpCodes.Ldarg, i + 1); 
                }

                il.EmitCall(OpCodes.Callvirt, method, null);
                il.Emit(OpCodes.Ret);
                typeBuilder.DefineMethodOverride(passThroughMethod, imethod);
            }
        }

      

When I try to instantiate a type, I get this error: "The body signature and declaration in the method implementation do not match." What am I missing here?

+3


source to share


1 answer


even if these methods are implemented in the parent type.

Since the parent type already implements the interface, the derived type does not need explicit passes (you may need to declare the parent implementations of the interface as virtual though).



Have a look at this answer: fooobar.com/questions/59642 / ...

+2


source







All Articles