mercredi 2 octobre 2019

Updating .NET Standard libraries without republishing the consuming site

I'm starting work on an ASP.NET MVC Core site. It is a parent site that contains subsites. Each subsite is its own .NET Standard library that uses embedded views. My boss would like us to be able to update these subsites by copying the .NET Standard libraries to the server without using NuGet and without republishing the parent site. He thinks we could use reflection to do this.

At first I thought this was a fine idea, but, given the way NuGet automatically handles bringing in any dependencies, it seems that doing it this way would take more time and effort than you'd save. I suppose my question is this: can you folks think of a fairly efficient way to update .NET Standard libraries, including all dependencies, that wouldn't involve updating NuGet packages and republishing the site?





C# Expression Specified cast is not valid

How to pass parameters using Expression.Invoke()?

If I use EventName = "ParameterlessAction" (trying to subscribe on parameterless Action)

-> everything works: created delegate can be subscribed on parameterless Action,

but if I try to use EventName = "BoolAction" (trying to subscribe on Action<bool>)

-> InvalidOperationException: Incorrect number of arguments cause I don't handle any parameters.

public class DelegateTest
    {
        public event Action ParameterlessAction;
        public event Action<bool> BoolAction;
        public DelegateTest()
        {
            string EventName = "ParameterlessAction";
            EventInfo eventInfo = typeof(DelegateTest).GetEvent(EventName);
            MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
            var parameters = methodInfo.GetParameters();
            Type[] types = new Type[parameters.Length];
            for (int i = 0; i < types.Length; i++)
            {
                types[i] = parameters[i].ParameterType;
            }
            Delegate del = CreateDelegate(types, typeof(void));
            eventInfo.AddEventHandler(this, del);
            ParameterlessAction?.Invoke();
            BoolAction?.Invoke(false);
            BoolAction?.Invoke(true);
        }
        public void PrintMessage(string msg)
        {
            Console.WriteLine(msg);
        }
        public Delegate CreateDelegate(Type[] parameterTypes, Type returnType)
        {
            PrintMessage("Total params: " + parameterTypes.Length);
            var parameters = parameterTypes.Select(Expression.Parameter).ToArray();
            Expression body;
            if (parameters.Length == 0)
            {
                PrintMessage("Creating parameterless lambda...");
                Expression<Action> parameterlessDel = () => PrintMessage("Parameterless");
                InvocationExpression invocator = Expression.Invoke(parameterlessDel);
                body = invocator;
            }
            else if (parameters.Length == 1)
            {
                Type type = parameters[0].Type;
                if (type == typeof(bool))
                {
                    PrintMessage("Creating <bool> lambda...");
                    Expression<Action<bool>> boolDel = (b) => PrintMessage("Bool[" + b.ToString() + "]");


                    //How to pass parameter here?


                    InvocationExpression invocator = Expression.Invoke(boolDel);
                    body = invocator;
                }
                else
                {
                    throw new Exception();
                }
            }
            else
            {
                throw new Exception();
            }
            var lambda = Expression.Lambda(body, false, parameters);
            return lambda.Compile();
        }
    }




How to call a method for all objects in a class using reflection for below case?

for (final Field field : someClass.getClass().getDeclaredFields()) {
                final Method getId = field.getType().getMethod("getId");
                getId.setAccessible(true);
                SomeComponent obj = (SomeComponent)getId.invoke(field.getType().newInstance());
}

I have objects in someClass who all are subclass of another class which has function getId. I have two objects of the same class in someClass which has following constructor.

 public Object1(SomeComponent id) {
      super(id);
   }

Other objects have following constructor :

public Object2() {
      super(SomeComponent.CORRESPONDING_ID);
   }

Do note that SomeComponent is a enum class.

So when I call newInstance() method, it works fine for every Object with constructor of type Object2 but in case of Object1 no instance is created.





Accessing null value leads to application fail / C#

I'm just looping and appending my properties to a big string:

output.Append(property.GetValue(this).ToString()));

When app braks in that moment property represent a ProductNumber which is a string, value of this is Product object which has value of ProductNumber = null, so I've tried something like this:

output.Append(property.GetValue(this)?.ToString()));

But anyway it breaks..

How could I improve this code to avoid breaking there?

Thanks

Cheers





mardi 1 octobre 2019

Use Tuple instead of Array of Union within Type

Is there a way to more strictly type the following two functions toCsv() and toArray() such that typeof csv is

[["key", "life", "goodbye"], [string, number, boolean]]

instead of

[("key" | "life" | "goodbye")[], ...(string | number | boolean)[]]

and typeof original is the same as typeof values instead of

{ key: any, life: any, goodbye: any }[]

I realize that iteration order of { key: 'value', life: 42, goodbye: false } using for...in is not guaranteed and I'm fine with that. Any consistent order that aligns keys with respective values for each row is acceptable, even if the TypeScript compiler doesn't produce the same order as runtime, since the usage doesn't rely on any particular ordering.

type Key<T> = Extract<keyof T, string>;
type Column<T> = [Key<T>, ...T[Key<T>][]];
type Columns<T> = [Key<T>[], ...T[Key<T>][][]];

function toCsv<T> (array: T[]): Columns<T> {
    const columns: Column<T>[] = [];

    for (const key in array[0]) {
        columns.push([key, ...array.map(value => value[key])]);
    }

    const keys: Key<T>[] = [];
    const rows: T[Key<T>][][] = array.map(() => []);

    for (const [key, ...values] of columns) {
        keys.push(key);

        for (const [index, row] of rows.entries()) {
            row.push(values[index]);
        }
    }

    return [keys, ...rows];
}

function toArray<T> (csv: Columns<T>): T[] {
    const [keys, ...rows] = csv;

    return rows.map(
        row => keys.reduce(
            (o, key, index) => Object.assign(o, { [key]: row[index] }),
            {} as Partial<T>
        ) as T
    );
}

const values = [{ key: 'value', life: 42, goodbye: false }];
const csv = toCsv(values);
const original = toArray(csv);




Guice binding reflected Class?> to a Method without knowing them at compile time

Let's say I have the follwoing as part of a Guice Module:

Method method = serviceClass.getMethod(methodName, Channel.class);
assert(Modifier.isStatic(method.getModifiers()));
Class<?> returnType = method.getReturnType();
bind(returnType).toProvider(?????)

What can I put there so that the provider calls method with the Channel parameter being injected. For example, if I knew the type at compile time, I would make something like:

@Provides
SomeStubType providesSomeStubType(Channel channel) {
    return SomeServiceClass.newStub(channel);
}

However, both SomeServiceClass, SomeStubType, and the newStub methods are known only when the module is being constructed via reflection. Further, SomeServiceClass is generated by the gRPC compiler and does not implement any special interface, although I could create a wrapper if needed.





How to get a member type from MemberInfo?

I search for Delegate members so I do 3 loops: search throw fields/properties/events.

I see that FieldInfo/PropertyInfo/Eventinfo are derived from MemberInfo, so I tried to use MemberInfo[].

If I have a FieldMember, I use x.FieldType, property - x.PropertyType

Is there any way to get Delegate type from MemberInfo?