Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Dec 07 22:08
    jeremydmiller commented #583
  • Dec 07 21:29
    jeremydmiller edited #583
  • Dec 07 21:29
    jeremydmiller closed #580
  • Dec 07 21:29
    jeremydmiller commented #580
  • Dec 07 21:29
    jeremydmiller demilestoned #580
  • Dec 07 14:39
    jeremydmiller demilestoned #562
  • Dec 07 14:39
    jeremydmiller milestoned #562
  • Dec 07 12:51
    jeremydmiller commented #562
  • Dec 06 20:45
    jeremydmiller closed #574
  • Dec 06 20:45

    jeremydmiller on master

    Better Disposal mechanics to ge… (compare)

  • Dec 06 19:47
    jeremydmiller closed #582
  • Dec 06 19:47
    jeremydmiller commented #582
  • Dec 06 19:47

    jeremydmiller on master

    Little rename and method access… Local routing improvements, new… (compare)

  • Dec 06 18:45
    jeremydmiller closed #563
  • Dec 06 18:45

    jeremydmiller on master

    New Endpoint.ReplyUri() method New Endpoint.ReplyEndpoint() me… Little tweak to ReplyUri mechan… (compare)

  • Dec 06 18:44
    jeremydmiller commented #563
  • Dec 06 18:39
    jeremydmiller commented #563
  • Dec 06 18:39
    jeremydmiller commented #563
  • Dec 06 18:39
    jeremydmiller commented #563
  • Dec 06 16:18
    jeremydmiller closed #586
MOHIT KUMAR AGARWAL
@m-agarwal
Both dependencies are initialized in the same container.
Jeremy D. Miller
@jeremydmiller
You’re going to have to give more information than that. The last Use call wins
Christian Chicken
@robertfriberg_twitter
I just upgraded Net Framework from 4.6 to 4.7 on all the projects in a solution and now resolution is failing. Any known issues I should be aware of before digging in? We are using version 4.7.1 and everything was fine until the netfx upgrade.
Heres my registry for reference, in case you see anything apparently stupid:
https://gist.github.com/rofr/455506bb30eea3e0d2bfc53d06902249
Jeremy D. Miller
@jeremydmiller
I don’t know of any issues, and you know this too, right? https://jeremydmiller.com/2018/01/29/sunsetting-structuremap/
Christian Chicken
@robertfriberg_twitter
@jeremydmiller thanks, yes I've read the sunsetting post. One of the few good things about the project I'm working on is they have a wrapper function around resolution so swapping structuremap for something else is done in a few minutes. That said, I'm fine using it until we have a good reason to switch.
Christian Chicken
@robertfriberg_twitter

A quick follow up... I updated to Lamar (which was very simple btw) but have the same behavior. Reading the docs I found the following, which is probably causing my bug:

Behind the scenes, Lamar is using the Assembly.GetExportedTypes() method from the .Net CLR to find types and this mechanism is very sensitive to missing dependencies.

Jeremy D. Miller
@jeremydmiller
Have you tried the type scanning diagnostics in either yet? That’ll help you unravel any issues with that
Christian Chicken
@robertfriberg_twitter
reading that doc page as we "speak", I print out the WhatDoIHave at startup and I am missing all the services not implicitly registered from a specific assembly. All use the default convention but the interfaces are in a separate assembly, for example AccountService and IAccountService. But no worries, I will figure it out. Our assembly dependencies are pretty messed up, with lots of warnings so I'll start there. If I find anything worth noting I'll be sure to let you know. Cheers and thanks for taking time to respond!
Jeremy D. Miller
@jeremydmiller
If you’re getting missing registrations, it could easily be because there’s a missing dependency after you updated .Net versions
Christian Chicken
@robertfriberg_twitter
Yes, that was the cause, thank you. Now I have TypeRepository.AssertNoTypeScanningFailures(); and _container.AssertConfigurationIsValid(); as part of my startup, fail fast ftw. That helped me locate the assembly that was failing and also which dependency failed to load.
nsirangu
@nsirangu
Is it possible to call a structure map bound class dynamically by loading it from dll?
Jeremy D. Miller
@jeremydmiller
You could I guess through a Lambda registration, but should you do that?
nsirangu
@nsirangu
IS.Process is my genereated dll by above class file..
Assembly assembly = Assembly.LoadFile(_targetPath);
Type type = assembly.GetType("IS.Process.ProcessJob");
dynamic _processJob = container.GetInstance(type);
var task1 = _processJob.Start();
task1.Wait();
Jeremy D. Miller
@jeremydmiller
If the “type” is concrete, has public constructors, and all the dependencies are known by SM, then yes
nsirangu
@nsirangu
I am trying to call start method from a console application by loading the assembly dynamically. Any thoughts on it?
Jeremy D. Miller
@jeremydmiller
I really wouldn’t want to do that myself. What’s the point of doing that?
nsirangu
@nsirangu
Projects will be loaded on demand.
Actually these are configured in database or a configuration file.
Jeremy D. Miller
@jeremydmiller
Sounds brittle
nsirangu
@nsirangu
The idea behind this is, every dll represents a process, when ever the process gets triggered the respective dll and will be loaded and called the start method to process the request.
Jeremy D. Miller
@jeremydmiller
Why not just have them hard coded in the original project? You’re having to load them into the AppDomain anyway. Why bother trying to make the loading lazy? You can get issues with the dynamic loading sometimes too
nsirangu
@nsirangu
If it doesn't work. we will go for it.
But it's working without strucuture map injection.. when using structure map it's not loading the class.
Jeremy D. Miller
@jeremydmiller
Why not?
nsirangu
@nsirangu
No Idea. I stuck there and searching for a solution
Jeremy D. Miller
@jeremydmiller
Okay
tom33pr
@tom33pr

Morning, new here... not sure if I'm in the right place... Could you guys assist with the below or point to someone who could assist?
In the old version (2.5) of Structure Map it was possible to:
ForRequestedType<IEventStoreUnitOfWork<IDomainEvent>>()
.CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.OfConcreteType<EventStoreUnitOfWork<IDomainEvent>>();

ForRequestedType<IUnitOfWork>()
.TheDefault.Is.ConstructedBy(x => x.GetInstance<IEventStoreUnitOfWork<IDomainEvent>>());

How do I do it in the latest version? Any idea?
Jeremy D. Miller
@jeremydmiller
Did you look at the docs? https://structuremap.github.io/registration/registry-dsl/ is the relevant page
tom33pr
@tom33pr
Thanks Jeremy, will have a look
tom33pr
@tom33pr

This part is clear:
ForRequestedType<IEventStoreUnitOfWork<IDomainEvent>>()
.CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.OfConcreteType<EventStoreUnitOfWork<IDomainEvent>>();

I am lost with the second bit whereby I need to register IUnitOfWork with an instance of IEventStoreUnitOfWork<IDomainEvent>

Jeremy D. Miller
@jeremydmiller
What’s the exact syntax you’re using with 2.5?
tom33pr
@tom33pr
public class LocalRegistry : Registry
{
public LocalRegistry()
{
...
        ForRequestedType<IEventStoreUnitOfWork<IDomainEvent>>()
            .CacheBy(InstanceScope.Hybrid)
            .TheDefault.Is.OfConcreteType<EventStoreUnitOfWork<IDomainEvent>>();

        ForRequestedType<IUnitOfWork>()
            .TheDefault.Is.ConstructedBy(x => x.GetInstance<IEventStoreUnitOfWork<IDomainEvent>>());
        ...
    }
}
Thanks for looking in this btw
Jeremy D. Miller
@jeremydmiller
For<IUnitOfWork>().Use(x => x.GetInstance<IEventStoreUnitOfWork<IDomainEvent>>());
tom33pr
@tom33pr
hahahahah easy peasy....
Gentleman
thanks a million
Doug Slater
@slater1

Hi,

I'm using SM 4.7, and I'm looking to create a custom lifecycle which returns a singleton scoped to the requesting type, for example:

an instance of type B requests an A -> build an A
an instance of type B requests an A -> return same instance of A
an instance of type C requests an A -> build an A

My implementation fails in nested composition scenarios, for example:

an instance of type B injected into instance of type C requests an A -> build an A
an instance of type B injected into instance of type D requests an A -> should return same instance of A. My implementation creates a new instance.

Below is the implementation and above failing test case. As you can see, I'm relying on BuildSession.RootType. I found that ParentType was always null or equal to the RootType rather than the requesting type.

How would you change RequesterLifecycleObjectCache to make the test pass?

Thank you in advance,

Doug Slater

using Shouldly;
using StructureMap.Pipeline;
using System;
using System.Collections.Concurrent;
using System.Linq;
using Xunit;

namespace StructureMap.Testing.Acceptance
{
    /// <summary>
    /// Lifecycle which maintains a singleton instance 
    /// of each requested type A 
    /// for each requesting type B
    /// 
    /// <para/>
    /// See RequesterLifecycleObjectCache for details.
    /// </summary>
    public class RequesterLifecycle : ILifecycle
    {
        public string Description => "Lifecycle which maintains a singleton instance for each requested type A for each requesting type B";

        private readonly IObjectCache _cache = new RequesterLifecycleObjectCache();

        public void EjectAll(ILifecycleContext context)
        {
            FindCache(context).DisposeAndClear();
        }

        public IObjectCache FindCache(ILifecycleContext context)
        {
            return _cache;
        }
    } 

    /// <summary>
    /// IObjectCache which maintains a singleton instance 
    /// of each requested type A 
    /// for each requesting type B
    /// </summary>
    /// 
    /// Example:
    /// 
    ///    class A implements interface IA
    ///    In StructureMap, IA resolves to A with RequesterLifecycle
    /// 
    ///    Later...
    ///     
    ///    an instance of type B requests an IA (key: B:IA) -> build an A
    ///    an instance of type B requests an IA (key: B:IA) -> return same instance of A
    ///    an instance of type C requests an IA (key: C:IA) -> build an A
    public class RequesterLifecycleObjectCache : IObjectCache
    {
        /// <summary>
        /// Maps each unique requester/requested pair to its object instance.
        /// </summary>
        private readonly ConcurrentDictionary<string, object> _objects = new ConcurrentDictionary<string, object>();

        public int Count => _objects.Count;

        public bool Has(Type pluginType, Instance instance)
        {
            return false;
        }

        public void Eject(Type pluginType, Instance instance)
        {
        }

        public object Get(Type pluginType, Instance instance, IBuildSession session)
        {
            var buildSession = session as BuildSession;
            var requester = buildSession.ParentType ?? buildSession.RootType;

            var key = GetKey(requester, pluginType);
            return _objects.GetOrAdd(key, _ => buildWithSession(pluginType, instance, session));
        }

        protected virtual object buildWithSession(Type pluginType, Instance instance, IBuildSession session)
        {
            return session.BuildNewInOriginalContext(pluginType, instance);
        }

        public void DisposeAndClear()
        {
            var keys = _objects.Keys.ToList();

            foreach (var key in keys)
            {
                if (_objects.TryRemove(key, out object toDispose))
                {
                    if (toDispose != null && !(toDispose is Container))
                    {
                        SafeDispose(toDispose);
                    }
                }
            }
        }

        private static void SafeDispose(object target)
        {
            if (!(target is IDisposable disposable)) return;

            try
            {
                disposable.Dispose();
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Creates a key that is unique for the given requesting and requested type pair.
        /// 
        /// <para/>
        /// e.g. "B:IA" reads as "an instance of type B requests an instance of type IA"
        /// </summary>
        private string GetKey(Type requester, Type requested)
        {
            var requesterName = requester?.AssemblyQualifiedName ?? string.Empty;
            var requestedName = requested?.AssemblyQualifiedName ?? string.Empty;

            return $"{requesterName}:{requestedName}";
        }
    }
    public class Test
    {
        public interface IA { }
        public class A : IA { }

        public interface IHasA
        {
            IA A { get; set; }
        }

        public class HasA : IHasA
        {
            public IA A { get; set; }

            public HasA(IA a)
            {
                A = a;
            }
        }

        public interface IB
        {
            IHasA HasA { get; set; }
        }

        public class B : IB
        {
            public IHasA HasA { get; set; }

            public B(IHasA hasA)
            {
                HasA = hasA;
            }
        }

        public interface IC
        {
            IHasA HasA { get; set; }
        }

        public class C : IC
        {
            public IHasA HasA { get; set; }

            public C(IHasA hasA)
            {
                HasA = hasA;
            }
        }

        private IContainer _container;

        public Test()
        {
            _container = new Container(config =>
            {
                config.For<IA>().Use<A>().LifecycleIs<RequesterLifecycle>();

                config.For<IHasA>().Use<HasA>();
                config.For<IB>().Use<B>();
                config.For<IC>().Use<C>();
            });
        }

        [Fact]
        public void HandlesNestedComposition()
        {
            var hasA = _container.GetInstance<IHasA>();
            var hasAtoo = _container.GetInstance<IHasA>();

            var b = _container.GetInstance<IB>();
            var c = _container.GetInstance<IC>();

            hasA.ShouldNotBeSameAs(hasAtoo); // Ok
            hasA.A.ShouldBeSameAs(hasAtoo.A); // Ok

            b.HasA.A.ShouldBeSameAs(c.HasA.A); // Fails
        }
    }
}
Jeremy D. Miller
@jeremydmiller
I think you’d be better off just using some kind of ISomething<T> where T is the concrete class it’s being injected into. Then make the ISomething<> registration a singleton and off you go. Failing that, you could use a combination of a “missing name instance” and a policy that adds an inline dependency by name I suppose. I wouldn’t try to use the custom life cycle for this.
Doug Slater
@slater1
Jeremy, thanks for your feedback. Based on that, I'll abandon the custom lifecycle approach and try something else. I also saw the link about Lamar replacing StructureMap. I'll see if my team can begin a migration plan. Thanks for your time.
Master Whiz
@whizkidwwe1217
image.png
@jeremydmiller Hi, is there a way to resolve a service through Registry?
Jeremy D. Miller
@jeremydmiller
Registry is for configuration, not resolution. You know you can register services by lambdas that can in turn use the container later at runtime?
Master Whiz
@whizkidwwe1217
Ohh I see. I actually tried the lambdas but it didn't allow me to put a block statement until I figured out that I need to provide a description. Thanks Jeremy.