GithubHelp home page GithubHelp logo

Comments (19)

pauldotknopf avatar pauldotknopf commented on July 20, 2024 1

This resolve it. Should I make a pull request?

    /// <summary>
    /// A factory that lazy instantiates a type and always returns the same instance
    /// </summary>
    private class SingletonFactory : ObjectFactoryBase, IDisposable
    {
        private readonly Type registerType;
        private readonly Type registerImplementation;
        private readonly object SingletonLock = new object();
        private Dictionary<int, object> _Current = new Dictionary<int, object>();

        public SingletonFactory(Type registerType, Type registerImplementation)
        {
            //#if NETFX_CORE
            //              if (registerImplementation.GetTypeInfo().IsAbstract() || registerImplementation.GetTypeInfo().IsInterface())
            //#else
            if (registerImplementation.IsAbstract() || registerImplementation.IsInterface())
                //#endif
                throw new TinyIoCRegistrationTypeException(registerImplementation, "SingletonFactory");

            if (!IsValidAssignment(registerType, registerImplementation))
                throw new TinyIoCRegistrationTypeException(registerImplementation, "SingletonFactory");

            this.registerType = registerType;
            this.registerImplementation = registerImplementation;
        }

        public override Type CreatesType
        {
            get { return this.registerImplementation; }
        }

        public override object GetObject(Type requestedType, TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options)
        {
            if (parameters.Count != 0)
                throw new ArgumentException("Cannot specify parameters for singleton types");

            int hashCode = 0;
            // if the registered type is an open generic....
            if(registerType.IsGenericType && registerType.GetGenericArguments().All(x => x.FullName == null))
            {
                // then the requested type should have the parameters defined.
                hashCode = requestedType.GetGenericArguments().Sum(x => x.GetHashCode());
            }else
            {
                // just a regular old singleton registration with a single stored instance
                hashCode = 0;
            }

            lock (SingletonLock)
            {
                if (!_Current.ContainsKey(hashCode))
                    _Current[hashCode] = container.ConstructType(requestedType, this.registerImplementation, Constructor, options);
                return _Current[hashCode];
            }
        }

        public override ObjectFactoryBase SingletonVariant
        {
            get
            {
                return this;
            }
        }

        public override ObjectFactoryBase GetCustomObjectLifetimeVariant(ITinyIoCObjectLifetimeProvider lifetimeProvider, string errorString)
        {
            return new CustomObjectLifetimeFactory(this.registerType, this.registerImplementation, lifetimeProvider, errorString);
        }

        public override ObjectFactoryBase MultiInstanceVariant
        {
            get
            {
                return new MultiInstanceFactory(this.registerType, this.registerImplementation);
            }
        }

        public override ObjectFactoryBase GetFactoryForChildContainer(Type type, TinyIoCContainer parent, TinyIoCContainer child)
        {
            // We make sure that the singleton is constructed before the child container takes the factory.
            // Otherwise the results would vary depending on whether or not the parent container had resolved
            // the type before the child container does.
            GetObject(type, parent, NamedParameterOverloads.Default, ResolveOptions.Default);
            return this;
        }

        public void Dispose()
        {
            if (_Current == null)
                return;

            foreach(var value in _Current.Values)
            {
                if(value is IDisposable)
                    (value as IDisposable).Dispose();
            }
        }
    }

from tinyioc.

niemyjski avatar niemyjski commented on July 20, 2024 1

@Worthaboutapig I was added as a contributor within the past year and have been resolving and responding to things as I get time... Before that I was in the same shoes as you... A lot of the current requests need a look over again but last time I did they were out dated and out of sync.

from tinyioc.

pauldotknopf avatar pauldotknopf commented on July 20, 2024

Here is a failing unit test.

[TestFixture]
public class ContainerTests
{
    [Test]
    public void Can_store_open_generics_as_singleton()
    {
        // arrange
        var container = new TinyIoCContainer();
        // conventions say this will store as singleton by default
        container.Register(typeof(IOpenGeneric<>), typeof(OpenGeneric<>));

        // act
        var type1 = container.Resolve<IOpenGeneric<Type1>>();
        var type2 = container.Resolve<IOpenGeneric<Type2>>();

        // assert
        type1.ShouldNotBeNull();
        type2.ShouldNotBeNull();
        Assert.IsInstanceOf<OpenGeneric<Type1>>(type1);
        Assert.IsInstanceOf<OpenGeneric<Type1>>(type2);

        // arrange
        type1.Value = 2;
        type2.Value = 2;

        // act
        type1 = container.Resolve<IOpenGeneric<Type1>>();
        type2 = container.Resolve<IOpenGeneric<Type2>>();

        // assert
        type1.Value.ShouldEqual(2);
        type2.Value.ShouldEqual(2);
    }

    public interface IOpenGeneric<T>
    {
        int Value { get; set; }
    }

    public class OpenGeneric<T> : IOpenGeneric<T>
    {
        public OpenGeneric()
        {
            Value = 1;
        }

        public int Value{get;set;}
    }

    public class Type1
    { 
    }

    public class Type2
    {
    }
}

from tinyioc.

TeaDrivenDev avatar TeaDrivenDev commented on July 20, 2024

Hmmm.... I actually did pretty much the same thing yesterday because the issue came up on Stack Overflow. I think from a design perspective, it might be better to split this out into a GenericSingletonFactory. I would also rather assert on sameness for the second resolution attempt; the Value property seems a bit of a crutch. ;-)

from tinyioc.

Worthaboutapig avatar Worthaboutapig commented on July 20, 2024

Has this been resolved/ looked at? I don't see any pull requests. It's a pretty important feature...

from tinyioc.

TeaDrivenDev avatar TeaDrivenDev commented on July 20, 2024

@Worthaboutapig I couldn't find any pull requests or changes related to this either. It has apparently been fixed by at least @theonlylawislove and me, but as the project seemed to be all but abandoned, obviously nobody ever bothered with a pull request (at least that was my reason).

from tinyioc.

grumpydev avatar grumpydev commented on July 20, 2024

Its far from.abandoned, its in active use in countless projects and is the core of Nancy.

from tinyioc.

TeaDrivenDev avatar TeaDrivenDev commented on July 20, 2024

I am aware of its role in Nancy, but it looked rather dead around the time this issue was opened; there were lots of issues (like this one) and pull requests that never even got a reaction. (I even considered forking it, because it was important for my work at the time.)

from tinyioc.

Worthaboutapig avatar Worthaboutapig commented on July 20, 2024

I queried whether it had been fixed, as the current release doesn't resolve open generics correctly for me, so I wasn't convinced that @theonlylawislove had fixed it.

I just wanted clarification that it definitely should work...

from tinyioc.

grumpydev avatar grumpydev commented on July 20, 2024

@Worthaboutapig it should work yes, but it appears that it doesn't and as far as I can remember it's not something I've ever fixed.

from tinyioc.

grumpydev avatar grumpydev commented on July 20, 2024

@TeaDrivenDev : the main reason most PRs aren't brought in is because the next logical step for this, after the major perf work I did a while back, is to make it fully PCL, but that work has never been completed in the PR and I haven't had time yet to do it myself (PCLs aren't really something I've played much with).

from tinyioc.

Worthaboutapig avatar Worthaboutapig commented on July 20, 2024

Thanks. I'll try and take a look at it, though I moved on to the NInject plugin instead, as it worked ;) However, the simplicity of the TinyIoC defaults appeals to me.

from tinyioc.

klym1 avatar klym1 commented on July 20, 2024

Any progress on fixing the issue? This is a really annoying bug...

from tinyioc.

niemyjski avatar niemyjski commented on July 20, 2024

Can someone submit a pr

from tinyioc.

rpenha avatar rpenha commented on July 20, 2024

Really a annoying bug. No option but to change to another IoC.

:(

from tinyioc.

niemyjski avatar niemyjski commented on July 20, 2024

@rpenha, you could submit a pr for this.

from tinyioc.

Worthaboutapig avatar Worthaboutapig commented on July 20, 2024

Don't mean to be rude, but there's dozens of PRs outstanding already. I submitted a fairly simple one that I thought was pretty useful two years ago... and zilch.

If the existing requests are ignored, then why should people submit new ones?

Again, it's a great project and I don't particularly mean to bash the maintainers, but it's effectively dead- the last commit was in April; there's no concerted effort to keep development going or fix serious bugs.

from tinyioc.

berhir avatar berhir commented on July 20, 2024

We have this problem in one of our projects. I tried the solution from @pauldotknopf and for us it works.
Any plans to fix it in this repo @niemyjski?
The proposed solution is maybe not perfect, but it works. And it will unblock some developers. Not sure if someone has the time to implement a better fix.

from tinyioc.

niemyjski avatar niemyjski commented on July 20, 2024

If you can submit a pr with tests I’ll merge it

from tinyioc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.