Params keyword with tuple with delegate in it. C# - c#

I'm trying to create a function with the params keyword like this:
public static IHostBuilder Foo(this IHostBuilder hostBuilder, params (string key, Action<IConsulConfigurationSource> options)[] sources)
{
return hostBuilder.
}
But on the method call:
Host.Foo(("key", bar =>
{
bar. // `bar` can not determine type of IConsulConfigurationSource
}));
The Action<IConsulConfigurationSource> variable bar can not determine type of IConsulConfigurationSource.
When I've modified method like this:
public static IHostBuilder Foo(this IHostBuilder hostBuilder, params Action<IConsulConfigurationSource>[] options sources)
{
return hostBuilder.
}
It works perfectly:
Host.Foo(bar =>
{
bar.ReloadOnChange = true;
});
Any idea why this is happening?

Related

Is it possible to pass StartupService as a parameter in CreateHostBuilder?

In order to create the project generic, I would like to receive the StartupService as a parameter. Is it possible?
public static IHostBuilder CreateHostBuilder<T, TClass>(string[] args, T service, TClass clas, Type type) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
{
var SERVICE_PORT = EnvironmentVariable.Get("SERVICE_PORT", 8200);
webBuilder.UseUrls($"https://+:{SERVICE_PORT}");
webBuilder.UseStartup<StartupService>();
//webBuilder.Ser
})
.ConfigureServices(svc => { svc.Add(new ServiceDescriptor(type, service));
});
I would like something similar to:
public static IHostBuilder CreateHostBuilder<T>(string[] args, T service, Type type, **TClass StartupServiceFromExternalClass**)
Yes, you can use the overload of UseStartup that accepts a startupFactory:
public static IHostBuilder CreateHostBuilder<T, TStartup>(
string[] args,
T service,
Type type,
TStartup startupServiceFromExternalClass)
where TStartup : class
{
return Host
.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
var SERVICE_PORT = EnvironmentVariable.Get("SERVICE_PORT", 8200);
webBuilder.UseUrls($"https://+:{SERVICE_PORT}");
webBuilder.UseStartup(() => startupServiceFromExternalClass);
})
.ConfigureServices(svc => svc.Add(new ServiceDescriptor(type, service)));
}

Extending SerializedObject with generic get method

I would like to write an generic extension method for SerializedObject that could be used instead of FindProperty and then accessing whateverValue member, so I would be able to write so.Get<Bool>("myValue") instead of so.FindProperty("myValue").boolValue.
Here is how I would like to solve this if template specialization was a thing in C#:
public static T Get<T>(this SerializedObject so, string name) {
Debug.LogError("Get called with unsuported type!");
}
public static bool Get<bool>(this SerializedObject so, string name) {
return so.FindProperty(name).boolValue;
}
How can something like this be achieved in proper C#? I have also tried to add a System.Type parameter instead of specialization, but then what should the return type of such function be?
I would use a little bit of functional programming. One of the input parameters of the generic function would be another function that would define how the read the property:
public static T Get<T>(this SerializedObject so, string name, Func<SerializedProperty, T> getter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
return getter(property);
}
A couple of examples of how I would use it:
internal bool ExampleBoolValue(SerializedObject so) {
return so.Get("myBoolValue", (p => p.boolValue));
}
internal int ExampleIntValue(SerializedObject so) {
return so.Get("myIntValue", (p => p.intValue));
}
I don't have Unity installed on this machine so I'm not sure that Unity supports these .NET features.
UPDATE for setter method:
public static void Set(this SerializedObject so, string name, Action<SerializedProperty> setter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
setter(property);
}
Examples for setting a value:
internal void SetExampleBoolValue(SerializedObject so, bool newValue) {
so.Set("myBoolValue", (p => p.boolValue = newValue));
}
internal void SetExampleIntValue(SerializedObject so, int newValue) {
so.Set("myIntValue", (p => p.intValue = newValue));
}
Action takes 0..n parameters and does not return anything. Func takes 0..n parameters and has to return something.
You can use the magic of generic static to accomplish this.
The first class GetPropertyValue<T> will store your handler based on the type. The static handler initially be set to your "unsupported" message, but the static constructor will call the InitGetPropertyValue class to initialize all the handlers. Because this is within the static constructor of that class, it will only be called once, the first time the class is initialized.
Because the static variable of GetPropertyValue<int>.Get is different than the static variable GetPropertyValue<string>.Get, the handler for your type that you stored previously will be used each subsequent call.
public static class MyExtensions
{
private static class GetPropertyValue<T>
{
static GetPropertyValue()
{
InitGetPropertyValue.Initialize();
}
public static Func<SerializedObject, string, T> Get = (so, name) =>
{
Debug.Print("Get called with unsupported type!");
return default(T);
};
}
private static class InitGetPropertyValue
{
static InitGetPropertyValue()
{
Debug.Print("Initializing property getters");
GetPropertyValue<int>.Get = (so, name) => (int)so.FindProperty(name) ;
GetPropertyValue<Guid>.Get = (so, name) => (Guid)so.FindProperty(name);
GetPropertyValue<string>.Get = (so, name) => so.FindProperty(name).ToString();
}
public static bool Initialize()
{
return true;
}
}
public static T Get<T>(this SerializedObject so, string name)
{
return GetPropertyValue<T>.Get(so, name);
}
}
While not a pretty solution, a working one would be sth like:
public static T Get<T>(this SerializedObject so, string name) {
if (typeof(T) == typeof(bool){
return (T)(object)so.FindProperty(name).boolValue;
}
else if {
...
}
else {
Debug.LogError("Get called with unsuported type!");
}
}
I'd personally go with sth like:
public static bool GetBoolean(this SerializedObject so, string name)
public static int GetInt(this SerializedObject so, string name)
The semantics stays the same, but implementation is cleaner.

How to call method with Func<string, T> as one of parameter

I have a class RemoteData like below,
public class RemoteData
{
public RemoteData(string Message, string IP)
{
this.IP = IP;
this.Message = Message;
}
public string IP;
public string Message;
}
Now I have a IObservable<T> method UdpStream like below,
public static IObservable<RemoteData> UdpStream(IPEndPoint endpoint, Func<string, RemoteData> processor)
{
return Observable.Using(() => new UdpClient(endpoint),
udpClient => Observable.Defer(() =>
udpClient.ReceiveAsync().ToObservable()).Repeat().Select(result => processor(Encoding.UTF8.GetString(result.Buffer))));
}
Now how to call UdpStream, how to pass Func parameter?
var stream = UdpStream(new IPEndPoint(IPAddress.Any, 514), 2nd Param);
Func<T, U> represents a delegate that takes a T parameter and returns U. You can initialize a Func<T, U> using a method reference that matches that signature, or using a lambda expression.
Using a Func<,> as parameter is a common idiom for a callback. For example, if you have a method similar to this:
public static void Method(Func<T, U> func)
{
// ...
}
We can expect that Method will call whaterver you pass in the func parameter. In fact, this happens in the code your present (the parameter Func<string, RemoteData> processor is called where it says processor(Encoding.UTF8.GetString(result.Buffer))).
Now, you have Func<string, RemoteData>, thus you need a method that takes string and returns RemoteData. For example:
public static RemoteData Example(string input)
{
// ...
}
// ...
var observable = UdpStream(endpoint, Example);

dynamic delegate to pass a method as parameter in C#

Is there any way to use DLR to reference a method in C#?
In dynamic languages like JavaScript or Python I could easily pass a method as an argument to another method. In C# being statically typed language, I either use Delegate type which needs lots of casting:
public static void AddMethod(Delegate del)
{
// implementation
}
and then use casting whenever I call this method
static void Main(string[] args)
{
AddMethod(new Func<object, bool>(Test));
}
public static bool Test(object obj)
{
return true;
}
Or, I need to define dozens of overloads to satisfy any method calls:
public static void AddMethod<TResult>(Func<TResult> method)
{
}
public static void AddMethod<T, TResult>(Func<T, TResult> method)
{
}
public static void AddMethod<T1, T2, TResult>(Func<T1, T2, TResult> method)
{
}
public static void AddMethod<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> method)
{
}
Is there any cleaner way to define an argument as a placeholder for all other methods? (I'm trying to avoid MethodInfo or other Reflection stuff here)
I was trying something like this:
public delegate dynamic DynamicDelegate(params dynamic[] args);
public static void AddMethod(DynamicDelegate method)
{
}
But the compiler doesn't seem to accept a statically typed method for a dynamically declared delegates!
Any other thoughts?
You can use a simple Action
void AddMethod(Action action) //or void AddMethod(Func<TResult> fxn)
{
}
and call as
AddMethod(()=>Test(obj));
or
AddMethod(()=>Test(obj1,obj2));
--EDIT--
AddMethod(() => Math.Max(1,3));
AddMethod(() => (int)Math.Sqrt(4));
AddMethod(() => new int[]{8,5,6}.Min())
void AddMethod(Func<int> fxn)
{
int i = fxn() * fxn(); // <---
}
Since .NET doesn't allow delegates with an unknown parameter syntax (this would approximate C void pointers, which is not something you want in a type-safe language), the closest thing that allows a variable argument list would be to pass an array of object arguments (i.e. object MyMethod(params object[] args)).
However, since this array is also an object reference, you can suffice with a single object reference:
object MyMethod(object arg))
The .NET framework also does this, see e.g. the ParameterizedThreadStart delegate)
So the basic idea is that you require that the user writes his code as a method that matches the above signature, and in turn it can receive any variable list of arguments of any type or size.
see below
Logger coreLogger;
Logger coreErrorLogger;
public Core()
{
PassByReference timestamp = new PassByReference(Timestamp);
coreLogger = Logger.GetLogger("LiTHiuM Core");
coreLogger.SetFormat("[{0}][LiTHiuM Core]: ", timestamp);
coreLogger.AddLogger(Log);
coreErrorLogger = Logger.GetLogger("LiTHiuM Core Error");
coreErrorLogger.SetFormat("[{0}][LiTHiuM Core (ERROR)]: ", timestamp);
coreErrorLogger.AddLogger(Error);
}
public string Timestamp(params dynamic[] args)
{
return DateTime.Now.ToString();
}
public delegate dynamic Reference(params dynamic[] args);
public class PassByReference
{
Reference reference;
public PassByReference(Reference reference)
{
this.reference = reference;
}
public override string ToString()
{
return this.reference().ToString();
}
}
public class Logger
{
static Dictionary<string, Logger> logFormatDict = new Dictionary<string, Logger>();
private List<LoggerDelegate> loggerDelegates = new List<LoggerDelegate>();
public static Logger GetLogger(string name)
{
if (logFormatDict.ContainsKey(name))
{
return logFormatDict[name];
}
else
{
var newLogFormat = new Logger(name, "");
logFormatDict.Add(name, newLogFormat);
return newLogFormat;
}
}
private event LoggerDelegate loggingEvent;
private Logger(string name, string format, params dynamic[] args)
{
this.Name = name;
this.format = format;
this.args = args;
}
public void AddLogger(LoggerDelegate logger)
{
if (!loggerDelegates.Contains(logger))
{
loggingEvent += logger;
loggerDelegates.Add(logger);
}
}
public void RemoveLogger(LoggerDelegate logger)
{
if (loggerDelegates.Contains(logger))
{
loggingEvent -= logger;
loggerDelegates.Remove(logger);
}
}
public void Log(string text, params dynamic[] args)
{
this.Invoke(String.Format(text, args));
}
public void Invoke(string text, params dynamic[] args)
{
loggingEvent.Invoke(this.ToString() + text, args);
}
public void SetFormat(string format, params dynamic[] args)
{
this.args = args;
this.format = format;
}
public string Name
{
get;
set;
}
string format;
dynamic[] args;
public override string ToString()
{
return String.Format(format, args);
}
}

C#. Add polymorphism for legacy code

Assume we have legacy classes, that can't be modified:
class Foo
{
public void Calculate(int a) { }
}
class Bar
{
public void Compute(int a) {}
}
I want to write a helper with such signature:
void Calc(object obj, int a);
Notice, that the first argument is of type 'object'. The test code should be some like this:
ExampleX.Calc((object)new Foo(), 0);
ExampleX.Calc((object)new Bar(), 0);
The question is, what implementation you can imagine in addition to these:
// Using If/then
class Example1
{
public static void Calc(object obj, int a)
{
if (obj is Foo)
((Foo)obj).Calculate(a);
else if (obj is Bar)
((Bar)obj).Compute(a);
}
}
// Using reflection
class Example2
{
private static Dictionary<Type, MethodInfo> _methods = new Dictionary<Type, MethodInfo>();
static Example2()
{
_methods.Add(typeof(Foo), typeof(Foo).GetMethod("Calculate"));
_methods.Add(typeof(Bar), typeof(Bar).GetMethod("Compute"));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()].Invoke(obj, new object[] { a });
}
}
// Using delegates
class Example3
{
private delegate void CalcDelegate(object obj, int a);
private static Dictionary<Type, CalcDelegate> _methods = new Dictionary<Type, CalcDelegate>();
static Example3()
{
_methods.Add(typeof(Foo), (o, a) => ((Foo)o).Calculate(a));
_methods.Add(typeof(Bar), (o, a) => ((Bar)o).Compute(a));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()](obj, a);
}
}
// Using Reflection + overloaded methods
class Example4
{
private delegate void CalcDelegate(object obj, int a);
public static void Calc(object obj, int a)
{
Type[] types = new Type[] {
obj.GetType(), typeof(int)
};
typeof(Example4).GetMethod("Calc", types).Invoke(null, new object[] { obj, a });
}
public static void Calc(Foo obj, int a)
{
obj.Calculate(a);
}
public static void Calc(Bar obj, int a)
{
obj.Compute(a);
}
}
Thanks!
Use extension methods to essentially add a new function to an existing type.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
This is how I would write the solution. It reduces the risk of type safety problems in the code and eliminates reflection.
class Example2
{
private static Dictionary<Type, Action<object,int>> _methods = new Dictionary<Type, Action<object,int>>();
static Example2()
{
Add<Foo>( (f,a) => f.Calculate(a) );
Add<Bar>( (b,a) => b.Compute(a) );
}
public static void Calc<TSource>(TSource source, int a)
{
_methods[typeof(TSource)](source,a);
}
public static void Add<TSource>(Action<TSource,int> del)
{
Action<object,int> wrapper = (x,i) => { del((TSource)x, i); };
_methods[typeof(TSource)] = wrapper;
}
}
you could always use the adapter pattern to implement the unchangeable legacy objects, without breaking any objects dependant on its functionality, while still being ableto implement your own (new) functionality to the object.
I would go for example 1, because its the simplest one and most obvious.
I would use Example 2 only if you expect new types of objects with one of these two methods, and example 3 only if you have a lot (tens if not hundreds) of objects and performance starts being an issue.
Edit: Or extension methods if you are .Net 3

Categories

Resources