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

Override MethodProcessor #356

Open
ezarzone opened this issue Mar 4, 2023 · 6 comments
Open

Override MethodProcessor #356

ezarzone opened this issue Mar 4, 2023 · 6 comments

Comments

@ezarzone
Copy link

ezarzone commented Mar 4, 2023

Hi!
We want to override MethodProcessor for change some behaviours. I make some testing but I cannot replace original MethodProcessor. @ENikS Some ideas for that?

Sample code:

    public class CustomMethodProcessor : MethodProcessor
    {
        public CustomMethodProcessor(IPolicySet policySet, UnityContainer container) : base(policySet, container)
        {
        }

    }

But using Register doesn't Works:

var container = new UnityContainer();
container.RegisterType<MethodProcessor, CustomMethodProcessor>();

I'm tying to use Extension but no lucky :(

Regards,

@ENikS
Copy link
Contributor

ENikS commented Mar 4, 2023

Look at this example

@ezarzone
Copy link
Author

ezarzone commented Mar 4, 2023

This is the code, but i don't know how I can get the Policy.

    public class CustomMethodProcessor : MethodProcessor
    {
        public CustomMethodProcessor(IPolicySet policySet, UnityContainer container) : base(policySet, container)
        {
        }

        public override IEnumerable<object> Select(Type type, IPolicySet registration)
        {
            return base.Select(type, registration);
        }
    }

And the extension:

    public class CustomUnityContainerExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            // Add the custom strategy to the strategy chain
            Context.Strategies.Add(new CustomMethodProcessorStrategy((UnityContainer)Container), UnityBuildStage.TypeMapping);
        }
    }

    public class CustomMethodProcessorStrategy : BuilderStrategy
    {
        private UnityContainer _container;

        public CustomMethodProcessorStrategy(UnityContainer container)
        {
            _container = container;
        }

        //TODO: How to replace MethodProcessor
        public override void PreBuildUp(ref BuilderContext context)
        {
            var registration = context.Registration;
            var typeToBuild = registration.RegisteredType ?? registration.MappedToType;

            //TODO: How to get the policy from the container?
            var methodProcessor = new CustomMethodProcessor(context.Policies, _container);
            var policy = context.Policies.Get<IMethodCallPolicy>(typeToBuild, registration.Name);
            policy.Methods.Insert(0, methodProcessor.Select);
        }
    }

If you have an idea, can you share it? :)

Thanks!

@ezarzone
Copy link
Author

ezarzone commented Mar 4, 2023

I'm trying using reflection for replace it, but no lucky too..

public class CustomUnityContainerExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        // Get the FieldInfo for the 'methodProcessor' private field in the UnityContainer class
        var methodProcessorField = typeof(UnityContainer).GetField("methodProcessor", BindingFlags.Instance | BindingFlags.NonPublic);

        // Get the current MethodProcessor instance from the container
        var currentMethodProcessor = (MethodProcessor)methodProcessorField.GetValue(Container);

        // Create an instance of your custom MethodProcessor and replace the current MethodProcessor instance with it
        var customMethodProcessor = new CustomMethodProcessor(currentMethodProcessor.Policies, Container);
        methodProcessorField.SetValue(Container, customMethodProcessor);
    }
}

I know that Method Policies are added in SetDefaultPolicies, but I don't know how change that:

        internal Action<UnityContainer> SetDefaultPolicies = (UnityContainer container) =>
        {
            // Default policies
            container.Defaults = new InternalRegistration(typeof(BuilderContext.ExecutePlanDelegate), container.ContextExecutePlan);

            // Processors
            var fieldsProcessor = new FieldProcessor(container.Defaults);
            var methodsProcessor = new MethodProcessor(container.Defaults, container);
            var propertiesProcessor = new PropertyProcessor(container.Defaults);
            var constructorProcessor = new ConstructorProcessor(container.Defaults, container);

            // Processors chain
            container._processors = new StagedStrategyChain<MemberProcessor, BuilderStage>
            {
                { constructorProcessor, BuilderStage.Creation },
                { fieldsProcessor,      BuilderStage.Fields },
                { propertiesProcessor,  BuilderStage.Properties },
                { methodsProcessor,     BuilderStage.Methods }
            };

            // Caches
            container._processors.Invalidated += (s, e) => container._processorsChain = container._processors.ToArray();
            container._processorsChain = container._processors.ToArray();

            container.Defaults.Set(typeof(ResolveDelegateFactory), (ResolveDelegateFactory)OptimizingFactory);
            container.Defaults.Set(typeof(ISelect<ConstructorInfo>), constructorProcessor);
            container.Defaults.Set(typeof(ISelect<FieldInfo>), fieldsProcessor);
            container.Defaults.Set(typeof(ISelect<PropertyInfo>), propertiesProcessor);
            container.Defaults.Set(typeof(ISelect<MethodInfo>), methodsProcessor);

            if (null != container._registrations) container.Set(null, null, container.Defaults);
        };

@ezarzone
Copy link
Author

ezarzone commented Mar 5, 2023

Using this approach I can add a new "BuilderStage.Methods", but using this doesn't replace original one!

            var container = (UnityContainer)Context.Container;

            // Replace MethodProcessor with CustomMethodProcessor
            var defaultRegistration = new InternalRegistration(typeof(BuilderContext.ExecutePlanDelegate), container);
            var customProcessor = new CustomMethodProcessor(defaultRegistration, container);
            Context.BuildPlanStrategies.Add(customProcessor, BuilderStage.Methods);

@ezarzone
Copy link
Author

ezarzone commented Mar 5, 2023

I can use same approach from public class Diagnostic : UnityContainerExtension but are internal classes.

@ezarzone
Copy link
Author

ezarzone commented Mar 6, 2023

@ENikS Any ideas please?

@unitycontainer unitycontainer deleted a comment from ezarzone Mar 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants