Pass parameters to constructor, when initializing a lazy instance - c#

public class myClass
{
public myClass(String InstanceName)
{
Name = InstanceName;
}
public String Name { get; set; }
}
// Now using myClass lazily I have:
Lazy<myClass> myLazy;
Console.WriteLine(myLazy.Value.Name);
My question is how to pass InstanceName to myClass constructor when we are using a lazy instance ?

Try this:
Lazy<myClass> myLazy = new Lazy<myClass>(() => new myClass(InstanceName));
Remember that the expression is evaluated lazily, so if you change the value of the variable InstanceName before the constructor is called it might not do what you expect.

Lazy has two ways to initialize. The first is using T's default ctor (parameterless)
the second is accepting an Func that has customer initialization logic. you should use the second overload as mentioned here
http://msdn.microsoft.com/en-us/library/dd642329.aspx

You can't, Lazy<T> requires a parameterless constructor. You could use the Lazy<T>(Func<T>) constructor though, with a method that initializes the class.

I struggled with this today and in my use case, I didn't want to use parameters from the constructor. I wanted to use parameters from a consumer of my type. Something like this.
public class MyClass
{
private readonly Lazy< **something** > names;
public MyClass()
{
// Initialize the names here
this.names = new Lazy< **something ** > (() =>
{
// do something here based off of a birth date
// AND
// only do it one time (the first time the this.names.Value is called
});
}
public string GetName(DateTime birthDate)
{
return this.names.Value(birthDate);
}
}
I tried using the Lazy(Func) constructor as mentioned by #ibrahim's answer like this.
public class MyClass
{
private readonly Lazy<Func<DateTime,string>> names;
public MyClass()
{
// Initialize the names here
this.names = new Lazy<Func<DateTime, string>>(birthDate =>
{
this.getNamesAndBirthDates().ToDictionary(x => x.Item2, x => x.Item1).TryGetValue(birthDate, out var name);
return name;
});
}
public string GetName(DateTime birthDate)
{
return this.names.Value(birthDate);
}
private IEnumerable<(string, DateTime)> getNamesAndBirthDates()
{
// returns a list fetching it from where ever...
return new[]
{
("name", new DateTime(2000, 1, 1))
};
}
}
This didn't work the way I wanted. I wanted the following:
this.getNamesAndBirthDates().ToDictionary(x => x.Item2, x => x.Item1).TryGetValue(birthDate, out var name);
return name;
to only be called one time per unique birth date value. It makes sense as to why it works the way it does, it's just that I didn't want it to work like that. I ended up with the following code that allowed me to do all of the things I wanted.
public class MyClass
{
private readonly Func<DateTime, string> names;
public MyClass()
{
var container = new Dictionary<DateTime, Lazy<string>>();
// Initialize the names here
this.names = birthDate =>
{
if (container.TryGetValue(birthDate, out var result)) return result.Value;
result = new Lazy<string>(() =>
{
// This code is only executed one time per unique birth date
this.getNamesAndBirthDates().ToDictionary(x => x.Item2, x => x.Item1).TryGetValue(birthDate, out var name);
return name;
});
container.Add(birthDate, result);
return result.Value;
};
}
public string GetName(DateTime birthDate)
{
return this.names(birthDate);
}
private IEnumerable<(string, DateTime)> getNamesAndBirthDates()
{
// returns a list fetching it from where ever...
return new[]
{
("name", new DateTime(2000, 1, 1))
};
}
}
Now I get everything I wanted.
Execute a Lazy func with consumer parameters - not constructor parameters.
Ensure that the Lazy build up code is only done one time per unique parameter value (in this case birth date).
Execute the build up lazily. Meaning only execute the build up when needed (but have it defined in the constructor of the MyClass type)
This code is just an simple example. It doesn't really make sense to do what I'm doing here in real life. But I've used this concept in production and it worked good.

Related

C# - In a Generic Class, How Can I Set a Generically-Typed Function Delegate?

I have a generic class of two types, "MyClass<T,U>". Based on a parameter to the class constructor, I'd like to be able to set a "Func<T,U>" local variable in a class instance that can be called to efficiently invoke a static method with input type T and output type U. The work done on the input variable depends on the input type. Can this be done?
Here's some code I've been playing with...
namespace ConsoleApp {
public class MyClass<T, U> {
// First constructor. Pass in the worker function to use.
public MyClass(Func<T, U> doWork) {
_doWork = doWork;
}
// Second constructor. Pass in a variable indicating the worker function to use.
public MyClass(int workType) {
if (workType == 1) _doWork = Workers.Method1;
else if (workType == 2) _doWork = Workers.Method2;
else throw new Exception();
}
// User-callable method to do the work.
public U DoWork(T value) => _doWork(value);
// Private instance variable with the worker delegate.
private Func<T, U> _doWork;
}
public static class Workers {
public static ushort Method1(uint value) => (ushort)(value >> 2);
public static uint Method1(ulong value) => (uint)(value >> 1);
public static ushort Method2(uint value) => (ushort)(value >> 3);
public static uint Method2(ulong value) => (uint)(value >> 4);
}
public class Program {
public static void Main(string[] args) {
var mc1 = new MyClass<uint, ushort>(Workers.Method1);
var mc2 = new MyClass<ulong, uint>(Workers.Method1);
var mc3 = new MyClass<uint, ushort>(Workers.Method2);
var mc4 = new MyClass<ulong, uint>(Workers.Method2);
var mc5 = new MyClass<uint, ushort>(1);
var mc6 = new MyClass<ulong, uint>(1);
var mc7 = new MyClass<uint, ushort>(2);
var mc8 = new MyClass<ulong, uint>(2);
}
}
}
The first constructor works just fine: the compiler is able to infer the correct overload of the static worker method to pass as a parameter, which gets stored in the instance variable _doWork, and can be (reasonably) efficiently called.
The second constructor won't compile, however, The problem is the assignments to _doWork which fail because "No overload for 'Method_' matches delegate 'Func<T,U>'". I sort of get it but sort of don't. It seems the compiler knows what T and U are at compile time, is "substituting" them into the class definition when compiling, and, so, ought to be able to infer which worker method to use. Anyone know why not?
Anyway, for reasons not worth going into, I'd really like to make the second constructor work. The obvious thing to try is to "cast" Method1 or Method2 to Func<T,U>, but delegates aren't objects and can't be cast. I've found a couple of pretty ugly ways to do it (that are also horribly inefficient), but I can't help but feeling there is something easier I'm missing. Any other ideas?
EDIT: It sounds like I'm abusing generics. What I have are about 100 different combinations of possible T, U, Worker values (there's actually a fourth dimension, but ignore that), each that behave somewhat differently. I'm trying to avoid having to create a separate class for each combination. So this isn't "generics" in the sense of being able to plug in any types T and U. What, if any, alternatives are there?
Have you considered using something like a factory pattern and resolving the service in a manner similar to this example
void Main()
{
var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, InAppNotificationMessageProcessor>();
serviceCollection.AddSingleton<IMessageDeliveryProcessor, MessageProcessor>();
serviceCollection.AddSingleton<IMessageProcessorFactory, MessageProcessorFactory>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var factoryItem = serviceProvider.GetService<IMessageProcessorFactory>();
var service = factoryItem.Resolve(DeliveryType.Email);
service.ProcessAsync("", "", "");
}
public enum DeliveryType
{
Email,
InApp,
}
public class MessageProcessorFactory : IMessageProcessorFactory
{
private readonly IServiceProvider _serviceProvider;
public MessageProcessorFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;
public IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType)
=> _serviceProvider
.GetServices<IMessageDeliveryProcessor>()
.SingleOrDefault(processor => processor.DeliveryType.Equals(deliveryType));
}
public interface IMessageProcessorFactory
{
IMessageDeliveryProcessor? Resolve(DeliveryType deliveryType);
}
public interface IMessageDeliveryProcessor
{
DeliveryType DeliveryType { get; }
Task ProcessAsync(string applicationId, string eventType, string messageBody);
}
public class InAppNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.InApp;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("InAppNotificationMessageProcessor");
return Task.CompletedTask;
}
}
public class EmailNotificationMessageProcessor : IMessageDeliveryProcessor
{
public DeliveryType DeliveryType => DeliveryType.Email;
public Task ProcessAsync(string applicationId, string eventType, string messageBody)
{
Console.Write("MessageProcessor");
return Task.CompletedTask;
}
}
This doesnt address your code and your issue exactly, but based on what I see of your issue, this could help you in the direction of travel.
In your second constructor, you are attempting to assign something not directly compatible. What you're assigning is a method group, of which nothing in the method group can match a T or a U using the compiler's type inference rules.
One thing you can do is instead of trying to assign the delegates directly in your second destructor, you can instead assign a dispatcher method that will resolve this at runtime.
Your constructor could be changed to
public MyClass(int workType)
{
if (workType == 1) _doWork = Method1Dispatcher;
else if (workType == 2) _doWork = Method2Dispatcher;
else throw new Exception();
}
where you have dispatcher methods such as
public U Method1Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method1(x),
ulong x => (U)(object)Workers.Method1(x),
_ => throw new NotSupportedException()
};
}
public U Method2Dispatcher(T value)
{
return value switch
{
uint x => (U)(object)Workers.Method2(x),
ulong x => (U)(object)Workers.Method2(x),
_ => throw new NotSupportedException()
};
}
These methods use a double cast to get around the compile-time checks that prevent you from "equating", for instance, a uint and a T. Casting to object removes that constraint, and casts to another type, at runtime, could either succeed or fail. That's not typesafe, but if implemented carefully like the above, you at least encapsulate known (to us not the compiler) safe casts.
To test that this works, you can modify your Main method to prove it
var mc5 = new MyClass<uint, ushort>(1);
var mc5Result = mc5.DoWork(5);
Console.WriteLine($"Got result {mc5Result} of type {mc5Result.GetType().Name}");
var mc6 = new MyClass<ulong, uint>(1);
var mc6Result = mc6.DoWork(6);
Console.WriteLine($"Got result {mc6Result} of type {mc6Result.GetType().Name}");
var mc7 = new MyClass<uint, ushort>(2);
var mc7Result = mc7.DoWork(7);
Console.WriteLine($"Got result {mc7Result} of type {mc7Result.GetType().Name}");
var mc8 = new MyClass<ulong, uint>(2);
var mc8Result = mc8.DoWork(8);
Console.WriteLine($"Got result {mc6Result} of type {mc8Result.GetType().Name}");
Now, while this works, it's probably not the best solution because you say there are hundreds of combinations. Perhaps you can replace the switch with a reflection based way of obtaining the correct method, and then invoking it.

Initializing an array of generic collections with each a different generic argument

During the development of one of my projects, I encountered an issue regarding generic types.
The project requires me to write a class that would act as a source of list objects. Suppose I had the following class:
public class TablesProvider
{
private readonly List[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public List<TItem> GetTable<TItem>()
{
return (List<TItem>)_tables.Single(x => x is List<TItem>);
}
}
This class obviously doesn't work, because the List type is a generic type and therefore the generic arguments should be specified.
So I made an abstract type called MyList, that would be derived by a more specific type MyList<TItem> in order to escape this requirement, and edited the TablesProvider a little.
public class TablesProvider
{
private readonly MyList[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public MyList<TItem> GetTable<TItem>()
{
return (MyList<TItem>)_tables.Single(x => x is MyList<TItem>);
}
}
public abstract class MyList
{
// ...
}
public class MyList<TItem> : MyList, IList<TItem>
{
private readonly List<TItem> _elements = new List<TItem>();
public TItem this[int index]
{
get { return _elements[index]; }
set { _elements[index] = value; }
}
// ...
}
This works quite well. There is only one problem left. Suppose I had 45 different collections, each defined with a different generic argument. What would be the best way of initializing all of those collections? I cannot use a for loop here, since generic parameters are specified at compile-time and not at runtime, and therefore a construction like this wouldn't be possible:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
My ultimate goal is to have the luxury to just do something like this...
var table = _tablesProvider.GetTable<SomeClass>();
var element = table[3];
var propertyValue = element.SomeProperty;
... without the need to cast the variable element in order to access its type-specific members.
It is probably worth mentioning that the amount of different list objects is fixed to 45. This will not change. In theory, I could initialize the array line by line, or have 45 properties or variables instead. Both of these options, however, sound as a rather cheap solution to me, but I will accept one of them if there is no other way.
Any of you got some ideas? Am I doing this completely wrong? Should I consider an other structure?
Thanks in advance.
Yes, it is possible to do what you are describing if you use reflection.
Supposing that your hypothetical GenericParameters array is an array of Types (since you can't have an array of type identifiers), you can define this helper function:
private MyList MakeList(Type t)
{
return (MyList)Activator.CreateInstance(typeof(MyList<>).MakeGenericType(t));
}
And that will allow you to do this:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = new MyList[GenericParameters.Length];
for (int i = 0; i < GenericParameters.Length; i++)
{
_tables[i] = MakeList(GenericParameters[i]);
}
}
You can even use LINQ if you want:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = GenericParameters.Select(MakeList).ToArray();
}
Previous answer:
Well, the reality is that you're going to have a list of 45 different types somewhere, which pretty much means you're going to have 45 different lines of similar code. So one could say the goal is to make those lines as concise as possible.
One way to do so would be to add a helper function:
private void AddTable<T>()
{
_tables.Add(new MyTable<T>());
}
(this assumes changing _tables to a List<MyTable>)
Then you could just do:
AddTable<Type1>();
AddTable<Type2>();
AddTable<Type3>();
AddTable<Type4>();
this implementation works
public class TablesProvider
{
private readonly List<object> _tables;
public TablesProvider()
{
_tables = new List<object>();
}
public IList<TItem> GetTable<TItem>()
{
var lst = (List<TItem>)_tables.SingleOrDefault(x => x is List<TItem>);
if (lst == null)
{
lst = new List<TItem>();
_tables.Add(lst);
}
return lst;
}
}
it creates List of TItem when necessary; next time it returns the same list for TItem. it is lazy initialization
so you can do invoke
var table = _tablesProvider.GetTable<SomeClass>();
without any code like this:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
it is not ThreadSafe

Is there any way to infer an Action type, or a full Action?

I find myself (too) often using a construct like the following:
class MyClass
{
public TypeA ObjectA;
public TypeB ObjectB;
public TypeC ObjectC;
public List<TypeD> ListOfObjectD = new List<TypeD>();
public void DoSmth()
{
return SomeConstruct(
/*...*/
new Setter<TypeA>(a => ObjectA = a), // these are the
new Setter<TypeB>(b => ObjectB = b), // things I'm trying
new Setter<TypeC>(c => ObjectC = c), // to make shorter
new Setter<TypeD>(d => ListOfObjectD.Add(d)),
/*...*/
);
}
}
class Setter<T>
{
public Action<T> Action;
public Setter(Action<T> action)
{
Action = action;
}
}
Is there any way for the Setter class to infer the type of the Action and create the standard (T obj) => Member = obj Action by only passing the Member in some way? I'm thinking of something like:
new Setter(ObjectA)
which of course is not valid syntax, but should give you an idea what I'm trying to achieve. I'm using this construct literally hundreds of time in my code, so the code
saved by this small change would be tremendous.
Edit: Added the TypeD example. The part
new Setter<TypeD>(d => ListOfObjectD.Add(d))
can be simplified to
new Setter<TypeD>(ListOfObjectD.Add)
which is awesome because it cuts from the redundant code. If only <TypeD> could also be inferred it would be perfect. I'm looking for something like this for the others.
#Lazarus - basically the purpose is to return setters, so other objects can set certain members of the class (or it can do other stuff defined in the Action) without accessing the class itself, only the Setter object. The full list of reasons is long and convoluted, but the structuring of the program works like a charm and I doubt needs changing (the example of course is simplified and doesn't really make sense as is).
Edit 2: I found a good way to simplify things for List's:
static class SetterHelper
{
public static Setter<T> GetSetter<T>(this List<T> list)
{
return new Setter<T>(list.Add);
}
}
Now I can just use this:
ListOfObjectD.GetSetter()
which works perfectly! why can't I do the same for T directly? I tried this:
static class SetterHelper
{
public static Setter<T> GetSetter<T>(this T item)
{
return new Setter<T>(t => item = t); // THIS DOESN'T SET THE PASSED MEMBER
}
}
Of course it won't work as intended because it will set item, but not the passed member. I tried adding ref as (ref this T item) but it won't compile :(... It would have been perfect.
Best I can offer you is the following syntax:
Setter.For( () => ObjectA );
using this helper class
static class Setter
{
public static Setter<T> For<T>(Expression<Func<T>> e)
{
ParameterExpression[] args = { Expression.Parameter(((e.Body as MemberExpression).Member as FieldInfo).FieldType) };
Action<T> s = Expression.Lambda<Action<T>>(Expression.Assign(e.Body, args[0]), args).Compile();
return new Setter<T>(s);
}
}

C# initialization question

This might be lame, but here:
public interface Interface<T>
{
T Value { get; }
}
public class InterfaceProxy<T> : Interface<T>
{
public T Value { get; set; }
}
public class ImplementedInterface: InterfaceProxy<Double> {}
Now I want to create an instance of the ImplementedInterface and initialize it's members.
Can this be done somehow like this (using initialization lists) or the same behavior can only be achieved using the constructor with Double argument?
var x = new ImplementedInteface { 30.0 };
Can be done by:
var x = new ImplementedInteface { Value = 30.0 };
var x = new ImplementedInterface() { Value = 30.0 };
The only way to achieve what you're after is if your class implements IEnumerable<T> and has an Add method:
public class MyClass : IEnumerable<double>
{
public void Add(double x){}
}
Then you can do:
MyClass mc = new MyClass { 20.0 };
Obviously that's not what you want, because that doesn't set your Value and it allows you to add multiple values:
MyClass mc = new MyClass { 20.0, 30.0 , 40.0 };
Just go with the standard object initializes like others have pointed out:
var x = new ImplementedInterface() { Value = 30.0 };
You should be able to do:
var x = new ImplementedInterface {Value = 30.0};
var instance = new ImplementedInterface { Value = 30.0 }; will work. However, this isn't really the same set of operations as C++ initializer lists -- this is an object initializer. It initializes the new instance via the default constructor and then invokes the property setters for each property.
In other words, the object is constructed before the property setters run. If you want the values for the properties set before construction of ImplementedInterface completes, you'd have to write a constructor, as you noted. This distinction in behavior usually doesn't matter, but it's good to be aware of.
I am not sure if you have a special reason to use the interfaces that way but the following code might work for you.
public class ImplementedInterface2 : List<double> { }
public class test
{
public void x()
{
var x = new ImplementedInterface2() { 30.0 };
}
}
var x = new ImplementedInterface { Value = 30.0 };
You can definitely use an initialization list, but you have to specify what 30.0 is (this is true for any initialization list, not just the code you have):
var x = new ImplementedInteface { Value=30.0 };

Is it possible to use a c# object initializer with a factory method?

I have a class with a static factory method on it. I want to call the factory to retrieve an instance of the class, and then do additional initialization, preferablly via c# object initializer syntax :
MyClass instance = MyClass.FactoryCreate()
{
someProperty = someValue;
}
vs
MyClass instance = MyClass.FactoryCreate();
instance.someProperty = someValue;
No. Alternatively you could accept a lambda as an argument, which also gives you full control in which part of the "creation" process will be called. This way you can call it like:
MyClass instance = MyClass.FactoryCreate(c=>
{
c.SomeProperty = something;
c.AnotherProperty = somethingElse;
});
The create would look similar to:
public static MyClass FactoryCreate(Action<MyClass> initalizer)
{
MyClass myClass = new MyClass();
//do stuff
initializer( myClass );
//do more stuff
return myClass;
}
Another option is to return a builder instead (with an implicit cast operator to MyClass). Which you would call like:
MyClass instance = MyClass.FactoryCreate()
.WithSomeProperty(something)
.WithAnotherProperty(somethingElse);
Check this for the builder
Both of these versions are checked at compile time and have full intellisense support.
A third option that requires a default constructor:
//used like:
var data = MyClass.FactoryCreate(() => new Data
{
Desc = "something",
Id = 1
});
//Implemented as:
public static MyClass FactoryCreate(Expression<Func<MyClass>> initializer)
{
var myclass = new MyClass();
ApplyInitializer(myclass, (MemberInitExpression)initializer.Body);
return myclass ;
}
//using this:
static void ApplyInitializer(object instance, MemberInitExpression initalizer)
{
foreach (var bind in initalizer.Bindings.Cast<MemberAssignment>())
{
var prop = (PropertyInfo)bind.Member;
var value = ((ConstantExpression)bind.Expression).Value;
prop.SetValue(instance, value, null);
}
}
Its a middle between checked at compile time and not checked. It does need some work, as it is forcing constant expression on the assignments. I think that anything else are variations of the approaches already in the answers. Remember that you can also use the normal assignments, consider if you really need any of this.
Yes. You can use object initializer for already created instance with the following trick. You should create a simple object wrapper:
public struct ObjectIniter<TObject>
{
public ObjectIniter(TObject obj)
{
Obj = obj;
}
public TObject Obj { get; }
}
And now you can use it like this to initialize your objects:
new ObjectIniter<MyClass>(existingInstance)
{
Obj =
{
//Object initializer of MyClass:
Property1 = value1,
Property2 = value2,
//...
}
};
P.S. Related discussion in dotnet repository:
https://github.com/dotnet/csharplang/issues/803
You can use an extension method such as the following:
namespace Utility.Extensions
{
public static class Generic
{
/// <summary>
/// Initialize instance.
/// </summary>
public static T Initialize<T>(this T instance, Action<T> initializer)
{
initializer(instance);
return instance;
}
}
}
You would call it as follows:
using Utility.Extensions;
// ...
var result = MyClass.FactoryCreate()
.Initialize(x =>
{
x.someProperty = someValue;
x.someProperty2 = someValue2;
});
+1 on "No".
Here's an alternative to the anonymous object way:
var instance = MyClass.FactoryCreate(
SomeProperty => "Some value",
OtherProperty => "Other value");
In this case FactoryCreate() would be something like:
public static MyClass FactoryCreate(params Func<object, object>[] initializers)
{
var result = new MyClass();
foreach (var init in initializers)
{
var name = init.Method.GetParameters()[0].Name;
var value = init(null);
typeof(MyClass)
.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase)
.SetValue(result, value, null);
}
return result;
}
No, the object initializer can only be used on a call to "new" with the constructor. One option might be to add some additional args to your factory method, to set those values at object creation inside the factory.
MyClass instance = MyClass.FactoryCreate(int someValue, string otherValue);
Like everyone said, no.
A lambda as an argument has already been suggested.
A more elegant approach would be to accept an anonymous and set the properties according to the object. i.e.
MyClass instance = MyClass.FactoryCreate(new {
SomeProperty = someValue,
OtherProperty = otherValue
});
That would be much slower though, since the object would have to be reflected on for all the properties.
No, that's something you can only do 'inline'. All the factory function can do for you is to return a reference.

Categories

Resources