But this doesn't work, because those three parameters are not static (they're instance objects on the current method). None of the writeupsI've found address this. I need some way to pass those values into that lambda expression? The Lazy<> class looks like it's expecting an empty signature.

2 Answers
2

Well, what if the Lazy used the Instance property to work with an instance of your singleton to provide itself with the properties? Those fields can still be private since we're working with them from inside the class (clever), and the whole thing will still be lazy until Singleton.Instance is referenced for the first time during execution. However, the private fields MUST have proper values before your code attempts to get the Person property. If they're eagerly loaded when Singleton instantiates itself, that's fine.

Borrowing from C# In Depth, here's a quasi-lazy Singleton with a fully-lazy Person member initialized using a lambda that references the Singleton.

EDIT: If you have IoC, use IoC. You are currently trying to mix patterns; you're using IoC to "promote" an instance class to singleton using runtime rules, but then trying to instantiate a compiler-enforced lazy static property based on this faux-singleton's instance-scoped data fields. This is simply not going to work

Once you go IoC, EVERY dependency should be registered and injected. Register PersonManager with Ninject as the IPersonManager implementation, and then create a constructor for your main singleton DataAdapter that can be given a Func that produces an IPersonManager. You can usually define a custom function for this purpose, which in your case will leverage the IoC to provide the required instance data from the single DataAdapter instance kept in the container.

Caveat: those data fields must now be publicly readable to avoid some seriously ugly reflection; you can define the fields as read-only fields or get-only properties to prevent people tampering with them, but your consumers will be able to see them.

A good thought, but it won't work for me. I'm not implementing Singleton using a static property like this, it's being injected by ninject as a singleton. How would you do it if Singleton in this case weren't a singleton but a regular instance member?
–
ArbiterFeb 15 '12 at 18:23

Singleton currently has a constructor (the client object cannot be initialized without a connection string). If I get rid of the constructor I need to modify my injection to use property injection instead of constructor injection, a lot of hoops to jump through just to use the Lazy<> class. I'm thinking it's not the right tool for this.
–
ArbiterFeb 15 '12 at 19:11

I'm not saying get rid of the constructor; I'm saying make sure your DataAdapter, which is registered as a singleton with Ninject, has a constructor that accepts a Func<IPersonManager>, and make sure that Ninject has a registry for IPersonManager and knows what Func to provide to DataAdapter. Then, you can simply use the Func inside a property getter or your Lazy field to produce an IPersonManager on demand.
–
KeithSFeb 16 '12 at 15:16

My example is a simplification. There are dozens of those lazy Manager classes (which is why they're not directly exposed via Ninject). I want DataAdapter to manage these. All the manager classes share that client, which is why they're all children of DataAdapter. The double-lock check solves the problem easily, I was just wondering if Lazy<> could do the same in a more straight-forward manner. I don't want to create a giant constructor on DataAccess or inject all those other classes when their implementation is the same.
–
ArbiterFeb 16 '12 at 15:46

(those three arguments to the PersonManager constructor are
properties/fields on the current object.)

A constructor is used to initialize your object. The arguments you are trying to pass will have no value assigned to them at this point. If your object needs these values to be initialized properly then they need to be passed in when you initialize.

Although you can convert your property to a method and pass these values to a static GetInstance method you will only setting this once, the first time GetInstance is called. This is probably not a good idea but it can be done. I would convert you Person property to a Method and accept these parameters and use them to initalize the constructor. This does mean you won't be using Lazy<T> and your lines of code will increase but you will have much more predictable behavior.

You're incorrect about the objects not having a value, they're assigned a value within the constructor of the object. I'm not getting a null reference exception, I'm getting a compilation error because those fields cannot be found. I'm not sure how what you're suggesting is better than my (working) double-check lock solution I'm starting with.
–
ArbiterFeb 15 '12 at 18:17

@Arbiter it wasn't clear from the code you were initializing them. KeithS suggest should work for you. I second his suggestion on not mixing patterns.
–
sarveshFeb 15 '12 at 19:12