Giter Site home page Giter Site logo

impromptu-interface's Introduction

net4.0/netstd2.0 framework to allow you to wrap any object (static or dynamic) with a static interface even though it didn't inherit from it. It does this by emitting cached dynamic binding code inside a proxy.

ImpromptuInterface is available Nuget NuGet

Platform Status
NET4 (Win) Build status
NETSTD (Win/Mac/Linux) Build status

Some of the features of ImpromptuInterface have been moved into another library called Dynamitey, ImpromptuInterface depends on Dynamitey.

ImpromptuInterface.FSharp has been spun off into FSharp.Interop.Dynamic and also depends on Dynamitey.

ImpromptuInterface.MVVM has been spun off into it's own repo ImpromptuInterface.MVVM and only receives maitenance updates.

Quick Usage:

    using ImpromptuInterface;
    using Dynamitey;

    public interface IMyInterface{

       string Prop1 { get;  }

        long Prop2 { get; }

        Guid Prop3 { get; }

        bool Meth1(int x);
   }
   //Anonymous Class
    var anon = new {
             Prop1 = "Test",
             Prop2 = 42L,
             Prop3 = Guid.NewGuid(),
             Meth1 = Return<bool>.Arguments<int>(it => it > 5)
    };

    var myInterface = anon.ActLike<IMyInterface>();

OR

   //Dynamic Expando object
    dynamic expando = new ExpandoObject();
    expando.Prop1 ="Test";
    expando.Prop2 = 42L;
    expando.Prop3 = Guid.NewGuid();
    expando.Meth1 = Return<bool>.Arguments<int>(it => it > 5);
    IMyInterface myInterface = Impromptu.ActLike(expando);

impromptu-interface's People

Contributors

david-garcia-garcia avatar fearthecowboy avatar hmemcpy avatar jbtule avatar mattyellen avatar nickacpt avatar ocbaker avatar quetzalcoatl avatar sabotageandi avatar slang25 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

impromptu-interface's Issues

Feature: Proxy's based on abstract types and concreate types with virtual methods

Project Member Reported by jtuley, Apr 16, 2011
The method generation code would be the same pretty much. Proxy class creation code would need to change but should be easy. Would need a different target property name to reduce collisions. ActLike syntax wouldn't work would need new specific syntax

idea:

Proxy.New(params object[] args).Build(object target, params Type[] otherInterfaces)

Proxy.New(Type type, params object[] args).Build(object target, params Type[] otherInterfaces)

FeatureRequest, ActLike with possibility to map method names

Hi

I think it is not yet possible what I would like to do. Let's assume I have

public class MyAdder{
    public double Add(double a, double b){
        return a + b;
    }
}

and an interface

public interface ISumCalculater{
    double Sum(double value1, double value2);
}

What I would like to be able to do is:

MyAdder adder = new MyAdder();
ISumCalculater calculator = adder.ActLike<ISumCalculater>().MapMethod("Add", "Sum");
double result = calculator.Sum(1.0, 2.0);

So I would like to have the possibility to have different method names in the interface and the implementation and still have the possibility to use ActLike<>. So I could use implementations which are compatible on the 'logical level' (however that should be called), but not on the naming level (which from a functional point of view is secondary; whether I call a car a "car", "voiture" or "автомобиль" does not change its behavior and functionality).

Now my question is whether this (by some way that I overlooked) is already possible in your library. If not then I would be interested to know whether this library could be extended to support that scenario (not only technically but also whether it would fit "the intention" of the library in your opinion).

Potentially this also interesting of course for properties.

ActLike() fails with explicit interface implementation

I'm not sure if this is expected behavior.

interface IDo
{
    void Do();
}

sealed class DoNothing : IDo
{
    void IDo.Do() { }
}
class TheDoNothing
{
    [Test]
    public void CanActLike()
    {
        var instance = new DoNothing();
        var acting = instance.ActLike<IDo>();
        acting.Do(); // throws RuntimeBinderException
    }
}

I read about Dynamitey UsagePrivate but this produces the same result.

class TheDoNothing
{
    [Test]
    public void CanActLike()
    {
        var instance = new DoNothing();
        var context = new InvokeContext(instance, typeof(IDo));
        var acting = context.ActLike<IDo>();
        acting.Do(); // throws RuntimeBinderException
    }
}

Obviously this a toy example, but I'm running into real issues when trying to do something similar using DynamicActLike() with an interface type known only at runtime.

Generic interface with arguments not known until runtime?

I'm trying to implement a generic interface that looks like this:

public interface ISomethingProvider<T>
{
    IConfig Get(Func<ISomething, T> f);
}

At some point, I'm given a Type that represents a bound generic type.

How can I specify the signature for Get, if I don't have the T until later?

[macOS] The type initializer for 'Dynamitey.Dynamic' threw an exception

Trying wrap my service using impromptu-interface version 7.0.1-beta40.
This my code:

services.AddTransient<SongRepository>();
            services.AddTransient<ISongRepository>(ctx =>
            {
                var repo = ctx.GetRequiredService<SongRepository>();
                var logger = ctx.GetRequiredService<ILogger<SongRepository>>();
                var res = new Wrapper<SongRepository>(repo, logger);

                return res.ActLike<ISongRepository>();
            });

but throw exception on Mac:

Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
      An unhandled exception has occurred: The type initializer for 'Dynamitey.Dynamic' threw an exception.
System.TypeInitializationException: The type initializer for 'Dynamitey.Dynamic' threw an exception. ---> System.IO.FileLoadException: Could not load file or assembly 'System, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at Dynamitey.Dynamic..cctor()
   --- End of inner exception stack trace ---
   at Dynamitey.Dynamic.GenericDelegateType(Int32 paramCount, Boolean returnVoid)
   at ImpromptuInterface.Build.BuildProxy.GenerateCallSiteFuncType(IEnumerable`1 argTypes, Type returnType, MethodInfo methodInfo, TypeBuilder builder)
   at ImpromptuInterface.Build.BuildProxy.DefineCallsiteField(TypeBuilder builder, String name, Type returnType, Type[] argTypes)
   at ImpromptuInterface.Build.BuildProxy.MakeMethod(ModuleBuilder builder, MethodInfo info, TypeBuilder typeBuilder, Type contextType, Boolean nonRecursive, Boolean defaultImp)
   at ImpromptuInterface.Build.BuildProxy.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces)
   at ImpromptuInterface.Build.BuildProxy.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces)
   at ImpromptuInterface.Impromptu.ActLike[TInterface](Object originalDynamic, Type[] otherInterfaces)
...

Working fine on Window, didn't test on Linux.

Issue Loading Type Dynamically

I'm getting his exception when I try to dynamically get a type:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Failure has occurred while loading a type.
System.TypeLoadException: Failure has occurred while loading a type.
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at ImpromptuInterface.Build.BuildProxy.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces) in C:\Users\Micah\Downloads\impromptu-interface-master\impromptu-interface-master\ImpromptuInterface\src\EmitProxy\BuildProxy.cs:line 400
   at ImpromptuInterface.Build.BuildProxy.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces) in C:\Users\Micah\Downloads\impromptu-interface-master\impromptu-interface-master\ImpromptuInterface\src\EmitProxy\BuildProxy.cs:line 148
   at ImpromptuInterface.Impromptu.DynamicActLike(Object originalDynamic, Type[] otherInterfaces) in C:\Users\Micah\Downloads\impromptu-interface-master\impromptu-interface-master\ImpromptuInterface\src\Impromptu.cs:line 159
   at WebApplication1.DIService.ResolveCustomersService() in C:\Users\Micah\Downloads\impromptu-interface-master\impromptu-interface-master\WebApplication1\rvice.cs:line 31
   at WebApplication1.Pages.Index.OnAfterRender(Boolean firstRender) in C:\Users\Micah\Downloads\impromptu-interface-master\impromptu-interface-master\WebApplication1\Pages\Index.razor:line 28
   at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.NotifyRenderCompletedAsync()

The exception occurs on this line:
https://github.com/ekonbenefits/impromptu-interface/blob/master/ImpromptuInterface/src/EmitProxy/BuildProxy.cs#L399

And here is my code:

var type = typeof(ICustomersService);
var expando = new ExpandoObject() as IDictionary<string, object>;
//expando population code here
dynamic myInterface = Impromptu.DynamicActLike(expando, type.GetType());

The reason I have to do type.GetType(), is because the type handed into the method could be anything.

@jbtule is this a bug?

Interface with different interface collection as property

I cannot figure out how why ActLike is having issues in this particular case. I am testing a controller action that returns a JsonResult and I am attempting to do actionResult.Data.ActLike(typeof(IRow)). the returned object for that call has the outer properties populated just fine, but is having big problems with the 'rows' property. When I try to enumerate it, it says the object does not have GetEnumerator method. What is the proper way to do this? I have tried other iterations where the property is IRow[] which also does not work. Also I am unsure whether my call to ActLike needs the typeof(IRow) parameter,

            var zipPreferenceData = credentials.Select(s => new
            {
                id = s.Id,
                cell = new[] { "1", "2", "3", "4", "5" , "6" }
            });

            var jqGridData = new { page = 1, total = 1, records = credentials.Count, rows = zipPreferenceData };
            return new JsonResult { Data = jqGridData, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
    public interface IJqGridData
    {
        int page { get; set; }
        int total { get; set; }
        int records { get; set; }
        IList<IRow> rows { get; set; }
    }

    public interface IRow
    {
        long id { get; set; }
        string[] cell { get; set; }   
    }

var data = actionResult.Data.ActLike<IJqGridData>(typeof(IRow));

How to work with enum parameters and return values

I have an interface that I would like to duck type that returns enum types and takes enum types as parameters.
e.g.

public enum Status
{
    Started,
    Running,
    Finished,
}

public class Calculator
{
    public Status Calculate(CalculationType calculationType)
    {
        // ... some very complex calculations
        return Status.Finished;
    }
}

When attempting to call functions like Calculate with an impromtu interface created using ActLike<T> I receiving binding exceptions.
I noticed in the InterfaceDictionaryWrappedTest() mapping int to TestEnum works well but I cannot find a way to create an impromtu interface for something like the example above.
Is there a way to do this?

Failure when using generic structs in nullable contexts

Starting in v8, an exception is thrown when trying to use ActLike on an interface with a property that is a generic struct in a nullable context.

Here is the example code:

#nullable enable

public struct GenericStruct<T>
{
    public string Something { get; }

    public GenericStruct(string something)
    {
        Something = something;
    }
}

public interface IInterfaceWithGenericStructProperty
{
    GenericStruct<IInterfaceWithGenericStructProperty> StructProperty { get; }

    string SomeOtherProperty { get; }
}

And the corresponding test:

[Test]
public void GenericStructInNullableContextTest()
{
    var result = new
    {
        SomeOtherProperty = "test"
    }.ActLike<IInterfaceWithGenericStructProperty>();
}

The exception:

Message:
System.InvalidCastException : Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument]' to type 'System.Array'.

Stack Trace:
CustomAttributeBuilder.EmitValue(BinaryWriter writer, Type type, Object value)
CustomAttributeBuilder.ctor(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
ActLikeMaker.ToCustomAttributeBuilder(CustomAttributeData customAttributeData) line 1434
ActLikeMaker.EmitProperty(TypeBuilder typeBuilder, MethodBuilder getMethodBuilder, PropertyBuilder tMp, PropertyInfo info, MethodBuilder setMethodBuilder, PropertyEmitInfo emitInfo) line 1580
ActLikeMaker.MakePropertyHelper(ModuleBuilder builder, TypeBuilder typeBuilder, PropertyEmitInfo emitInfo, PropertyInfo info) line 1380
ActLikeMaker.MakeProperty(ModuleBuilder builder, PropertyInfo info, TypeBuilder typeBuilder, Type contextType, Boolean nonRecursive, Boolean defaultImp) line 875
ActLikeMaker.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces) line 446
ActLikeMaker.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces) line 200
ActLikeMaker.ActLike[TInterface](Object originalDynamic, Type[] otherInterfaces) line 90
Impromptu.ActLike[TInterface](Object originalDynamic, Type[] otherInterfaces) line 39
Basic.GenericStructInNullableContextTest() line 661

I suspect this may be caused by #49, since the code path that is generating the exception is first introduced in that PR.

See #57 for a fix.

Have proxy check if wrapping the same interface

This would be useful in the cases of wrapping with the same interface, but had an explicit implementation which wouldn't work with the DLR hence impromptu interface. Might be too much runtime work to be worth it, hard to say. Will think about it.

Source generators

I want to implement something similar to this package using the new source generators package,
Do you think it will be possible ?

Incorrect binder.ReturnType

Say we define a null object like this:

  public class Null<T> : DynamicObject where T:class
  {
    public static T Instance
    {
      get
      {
        if (!typeof(T).IsInterface)
          throw new ArgumentException("I must be an interface type");
    
        return new Null<T>().ActLike<T>();
      }
    }
  
    public override bool TryInvokeMember(InvokeMemberBinder binder, 
      object[] args, out object result)
    {
      result = Activator.CreateInstance(binder.ReturnType);
      return true;
    }
  }

And an interface like this

public interface ILog
{
  void Info(string msg);
  bool Warn(string msg);
}

Calling Null<ILog>.Instance.Warn("...") gives an exception because in TryInvokeMember, the value of binder.ReturnType is System.Object for some reason. Looks like ImpromptuInterface is failing to specify binder.ReturnType correctly on the basis of what the members actually are. binder.Name is correct, though.

Generic Function doesn't want to be duck-casted.

Reported by theajp01, Aug 27, 2012
What steps will reproduce the problem?

I don't know if it's supposed to work but I though it'd mention it.

  1. create an interface to duck-cast to:
    public class Thing {}

public interface ITest
{
List GetThings (Guid test) where T: Thing;
}

  1. make a dynamic object to duckcast.
    public class OtherThing : DynamicObject
    {
    }
  2. duck-cast it.
    dynamic ot = new OtherThing();
    ITest test = Impromptu.ActLike();

test.GetThings(Guid.Empty);

What is the expected output? What do you see instead?

I'd expect test to be of Type ITest.

Instead of that I Get a MissingMemberException.

What version of the product are you using? On what operating system?

Last version

Please provide any additional information below.

I love your work on ImpromptuInterface an awsome tool :)

Oct 16, 2012 comment remilavoie
Your OtherThing class needs to have the
List GetThings(Guid test)
function in order to act like an ITest.

Feature Request: ActLike<BaseClass>

Add ability to pass a Base Class Type to ActLike and have it generate that object.
Reasoning: Dynamic Entity Framework Core.

Sample Unit Test Usage for Entity Framework:

            dynamic testObject = new ExpandoObject();

            //dynamic testObjectContext = testObject.ActLike<DbContext>();
            dynamic testObjectContext = Impromptu.ActLike<DbContext>(testObject);

            Type testObjectContextType = testObjectContext.GetType();

            Assert.True(testObjectContextType.IsSubclassOf(typeof(DbContext)));

Null reference exception

System.NullReferenceException:

mscorlib.dll!System.Reflection.Emit.TypeBuilder.GetField(System.Type type, System.Reflection.FieldInfo field)   Unknown
ImpromptuInterface.dll!ImpromptuInterface.Build.EmitExtensions.GetFieldEvenIfGeneric(System.Type type, string fieldName)    Unknown
ImpromptuInterface.dll!ImpromptuInterface.Build.BuildProxy.EmitMethodBody(System.Reflection.Emit.MethodBuilder methodBuilder, System.Reflection.ParameterInfo[] paramInfo, ImpromptuInterface.Build.BuildProxy.MethodEmitInfo emitInfo) Unknown
ImpromptuInterface.dll!ImpromptuInterface.Build.BuildProxy.MakeMethod(System.Reflection.Emit.ModuleBuilder builder, System.Reflection.MethodInfo info, System.Reflection.Emit.TypeBuilder typeBuilder, System.Type contextType, bool nonRecursive, bool defaultImp) Unknown
ImpromptuInterface.dll!ImpromptuInterface.Build.BuildProxy.BuildTypeHelper(System.Reflection.Emit.ModuleBuilder builder, System.Type contextType, System.Type[] interfaces) Unknown
ImpromptuInterface.dll!ImpromptuInterface.Build.BuildProxy.BuildType(System.Type contextType, System.Type mainInterface, System.Type[] otherInterfaces) Unknown
ImpromptuInterface.dll!ImpromptuInterface.Impromptu.ActLike<TraceDB.Models.IRepository>(object originalDynamic, System.Type[] otherInterfaces)  Unknown
...

For GetFieldEventIfGeneric, the type is Impromptu_Callsite_Add_GUID and the fieldName Convert_Method.

InvalidCastException thrown from InvokeConstructor if passing more than 14 params arguments

I have a class that I'm creating dynamically via Impromptu.InvokeConstructor that has params arguments. If I pass in 14 arguments it works, but 15 causes an InvalidCastException:

System.InvalidCastException: The result type 'ImpromptuParamsArgs.MyClass' of the dynamic binding produced by binder 'Microsoft.CSharp.RuntimeBinder.CSharpInvokeConstructorBinder' is not compatible with the result type 'System.Type' expected by the call site.

Here is some example code:

    class Program
    {
        static void Main(string[] args)
        {
            var parameters = Enumerable.Range(0, 15).Select(i => i.ToString() as object).ToArray();
            var instance = Impromptu.InvokeConstructor(typeof(MyClass), parameters);
            Console.Out.WriteLine(instance.Args);
        }
    }


    public class MyClass
    {
        public readonly string Args;

        public MyClass(params string[] args)
        {
            Args = String.Join(",", args);
        }
    }

TypeLoadException with SpecialName attribute.

I'd like to dynamically wrap some COM interface which sadly has a SpecialName attribute, this leads to a crash in ImpromtuInterface.

A minimal Repro is:

        public interface IImpromptuBug
        {
            [SpecialName]
            void let_Value(object lppvReturn);
        }

        public class ImpromptuBug
        {
        }

        [TestMethod]
        public void TestImpromtpuBug()
        {
            var test = new ImpromptuBug();
            var b = test.ActLike<IImpromptuBug>(); // TypeLoadException
        }

It seems like Impromtu-Interface is not implementing the let_Value method. The interface I'm trying to wrap is https://msdn.microsoft.com/en-us/library/envdte.property.aspx

Updating ImpromptuInterface from 6.2.2 to 7.0.1 (latest version)

My project currently references ImpromptuInterface 6.2.2 and it works great. I am in the process of updating all my nuget packages to latest version.

When updating ImpromptuInterface from 6.2.2 to 7.0.1 I got 2 errors:

  • 'Impromptu' does not contain a definition for 'InvokeGet'
  • 'Impromptu' does not contain a definition for 'GetMemberNames'

My code:

if (Impromptu.GetMemberNames(sourceObject).Any(x => x == newPropertyPath))
{
var newSourceObject = Impromptu.InvokeGet(sourceObject, newPropertyPath);
}

It seems these methods does no longer exists.
Any help is much appreciated.

Add overload (or optional parameter) to ActLike to support case insensitivity

It is common for JSON to be camel-cased and .NET interfaces to be Pascal-cased. Adding case-insensitive binding similar to JSON.NET's behavior would be great. The use case comes up when deserializing JSON to dynamic.

The following two lines of code:

var dynamicValue = JsonConvert.DeserializeObject<dynamic>(value);
var duckType = Impromptu.ActLike<TInterface>(dynamicValue);

work as expected when the JSON properties are Pascal-cased but fail when they are camel-cased. Since JSON.NET is told to deserialize into dynamic, it does not bind like it would if you were deserializing to a specific class. Enabling case-insensitivity in the call to ActLike would solve the problem.

RuntimeBinderException trying to set a property after Activator.CreateInstance

Hello and thanks for this great project!

I am currently using this to generate a class from an interface at runtime:

var theInterface = Impromptu.ActLike<IImage>(new { });
var iimage = (IImage)Activator.CreateInstance(theInterface.GetType());
iimage.Id = "hi";

Unfortunately, I get an Exception on the 3rd line:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference'
Stack trace on Win10 x64 Core3.1:

   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at ActLike_IImage_ae9204a78c7144d991df6b0084d4e2da.set_Id(String value)
   ...

Stack trace on Blazor Chrome:

at (wrapper dynamic-method) System.Object.CallSite.Target(System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,object,string)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet] (System.Runtime.CompilerServices.CallSite site, T0 arg0, T1 arg1) <0x2fbe2e8 + 0x00248> in <filename unknown>:0 
at ActLike_IImage_d38621b4b95445c38e41839a8b0a07cc.set_Id (System.String value) <0x2fbadd0 + 0x00098> in <filename unknown>:0
...

Is there a certain way I should be doing that?

ActLike interface with default implementation produces exception

I am getting an exception when using an interface that contains default implementations.

public interface IJSObjectReferenceFacade
    {
        IJSObjectReference JSObjectReference { get; }

        bool TryInvokeAsync<TValue>(string identifier, object?[] args, out ValueTask<TValue> result)
        {
            result = default;
            return false;
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, args);
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, cancellationToken, args);
        }

        ValueTask<TValue> InvokeAsync<TValue>(string identifier, TimeSpan timeout, params object?[] args)
        {
            if (TryInvokeAsync<TValue>(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeAsync<TValue>(JSObjectReference, identifier, timeout, args);
        }

        bool TryInvokeVoidAsync(string identifier, object?[] args, out ValueTask result)
        {
            result = default;
            return false;
        }

        ValueTask InvokeVoidAsync(string identifier, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, args);
        }

        ValueTask InvokeVoidAsync(string identifier, CancellationToken cancellationToken, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, cancellationToken, args);
        }

        ValueTask InvokeVoidAsync(string identifier, TimeSpan timeout, params object?[] args)
        {
            if (TryInvokeVoidAsync(identifier, args, out var result)) {
                return result;
            }

            return JSFunctionalObjectReference.Default.InvokeVoidAsync(JSObjectReference, identifier, timeout, args);
        }
    }

...

return jsDynamicObject.ActLike<IJSObjectReferenceFacade>(new DynamicObject()); // error

Here the stacktrace:

Nachricht: 
    System.ArgumentException : The number of generic arguments provided doesn't equal the arity of the generic type definition. (Parameter 'instantiation')
  Stapelüberwachung: 
    RuntimeType.MakeGenericType(Type[] instantiation)
    BuildProxy.UpdateCallsiteFuncType(Type tFuncGeneric, Type returnType, Type[] argTypes)
    BuildProxy.MakeMethod(ModuleBuilder builder, MethodInfo info, TypeBuilder typeBuilder, Type contextType, Boolean nonRecursive, Boolean defaultImp)
    BuildProxy.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces)
    BuildProxy.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces)
    Impromptu.ActLike[TInterface](Object originalDynamic, Type[] otherInterfaces)
    JSDynamicObjectActivator.CreateInstance[T](IJSObjectReference jsObjectReference) Zeile 55
    JSDynamicObjectTests.Should_expect_identifier_as_passed() Zeile 37
    --- End of stack trace from previous location ---

I tried to look in BuildProxy.cs but I cannot effort the time currently to understand 2000 lines of code.

Exception Thrown on Blazor WASM

I am trying to use this package on my Blazor WASM (client-side) project. The goal is to reflect my database service set out to the client so service methods can be called without calling web APIs.

I'm running into this exception:

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Cannot emit a CustomAttribute with argument of type System.RuntimeType.
System.ArgumentException: Cannot emit a CustomAttribute with argument of type System.RuntimeType.
   at System.Reflection.Emit.CustomAttributeBuilder.Initialize(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
   at System.Reflection.Emit.CustomAttributeBuilder..ctor(ConstructorInfo con, Object[] constructorArgs)
   at ImpromptuInterface.Build.BuildProxy.BuildTypeHelper(ModuleBuilder builder, Type contextType, Type[] interfaces)
   at ImpromptuInterface.Build.BuildProxy.BuildType(Type contextType, Type mainInterface, Type[] otherInterfaces)
   at ImpromptuInterface.Impromptu.DynamicActLike(Object originalDynamic, Type[] otherInterfaces)
   at ImpromptuInterface.ActLikeCaster.TryConvert(ConvertBinder binder, Object& result)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[Object,IMyInterface](CallSite site, Object arg0)
   at WasmReload.Client.Services.DIService.ResolveCustomersService() in C:\Users\Micah\source\repos\WasmReload\WasmReload\Client\Services\DIService.cs:line 67
   at WasmReload.Client.Pages.Index.OnAfterRender(Boolean firstRender) in c:\Users\Micah\source\repos\WasmReload\WasmReload\Client\Pages\Index.razor:line 17
   at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync()
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.NotifyRenderCompletedAsync()

And here is my code: (from the front page of the repo)

   //Dynamic Expando object
    dynamic expando = new ExpandoObject();
    expando.Prop1 ="Test";
    expando.Prop2 = 42L;
    expando.Prop3 = Guid.NewGuid();
    expando.Meth1 = Return<bool>.Arguments<int>(it => it > 5);
    IMyInterface myInterface = Impromptu.ActLike(expando);

impromptu-interface/MVVM support for Metro apps

Reported by buskila, Dec 26, 2012
Description of feature:
It seems that the current version does not work in a Metro style app on win8 due to missing classes from the Metro .NET framework.

Any chance its possible to create a workaround or the missing objects are crucial and cant be reimplemented?

Jan 31, 2013 Delete comment Project Member #1 jtuley
They are kind of crucial, the interface proxying is a big part and that is all reflection emit which doesn't exist in WinRT, a lot of the other feature just use the dlr and that does work in WinRT. Technically Impromptu has an api in which you can pre-emit the interface proxies, so if i restructure to a portable library and just ommited emit code for the WinRT specific additions it might be something usable or just confusing. I'm probably going to restructure to a portable library at some point, just have too many project files to deal with, so we will see.

Generating serilizable proxies

I'm using the library to proxy an object as an interface, e.g.

[Serializable]
public class MyDTO
{
   Guid Id { get; set; }
}

public interface MyInterface 
{
   Guid Id { get; }
}

var obj = new MyDTO(...);
var interf = obj.ActLike<MyInterface>();

It works fine and proxy is generated as expected but the problem is that my DTO is serializable as I need to pass it around AppDomain boundaries but the generated proxy is non-serializable.

Is this supported or is it a bug? Any way I can work around it?

TryGetMember parameter GetMemberBinder's ReturnType always object #BUG

This's my usage:

public interface IMailClientConfig
{
string Host { get; }
int SmtpPort { get; }
}

    private class ConfigImpl : DynamicObject
    {
        private readonly Dictionary<string, string> _section;

        public ConfigImpl(string section)
        {
            _section = Sections[section];
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
             result = Convert.ChangeType(_section[binder.Name], binder.ReturnType);
            //binder.ReturnType always object , in SmtpPort should int , in Host  should string.

            return true;
        }
    }

IMailClientConfig r = new ConfigImpl("MailClient").ActLike();
var str = r.Host; // Working fine.
var num=r.SmtpPort; // Throw RuntimeBinderException. Can't cast string to int, see above

Now i only can make a 'patch' , but that's isn't beautiful coding.

private class ConfigImpl : DynamicObject
{
private readonly Dictionary<string, string> _section;
private readonly Dictionary<string, Type> _props;

        public ConfigImpl(string section)
        {
            _section = Sections[section];
            _props = typeof(T).GetProperties().ToDictionary(p => p.Name, p => p.PropertyType);
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (_section.ContainsKey(binder.Name) == false)
                throw new ArgumentException("Config not found");

            result = Convert.ChangeType(_section[binder.Name], binder.ReturnType);// _props[binder.Name]);
            return true;
        }
    }

ImpromptuMVVM: Dispatcher thread awareness

Reported by @WorldMaker Sep 21, 2012

Description of feature:

Silverlight, WPF, and Win8 all use a threading model where UI changes need to be marshalled (back) onto a "Dispatcher" thread (the UI thread). Good performant apps run operations on a background thread and then marshall changes back to the UI/Dispatcher thread.

C# 4.5 support for the async/await keywords help mitigate handling this dispatcher thread work in non-MVVM event handlers and it would nice for ImpromptuMVVM to support Dispatcher thread awareness as well.

The suggestion here would be to add the necessary checks to the pieces that call INotifyPropertyChanged, CommandExecuteChanged, etc events to check if they are running on the appropriate Dispatcher thread, and if they are not to call the suitable BeginInvoke(...) to do so.

A further suggestion to help make even easier to "do things the right way by default" would be to either default impromptu Commands to run on a background thread. It may be a breaking change to do that, so a better suggestion may be to support impromptu Commands that return Task (and by extension the C# 4.5 async keyword) and make sure those run in a background thread.

Usage case:

Contract.Prop1 = "value";
// ...more operation code here...
Dynamic.Prop2 = "other value";

Instead of:

App.Current.Dispatcher.BeginInvoke(() =>
{
Contract.Prop1 = "value";
});
// ...more operation code here...
App.Current.Dispatcher.BeginInvoke(() =>
{
Dynamic.Prop2 = "other value";
});

Also:

// Background commands
public Task Save(object p) {}
public async void Save(object p) {}

Notes:

I'm willing to contribute code to support this, but before I started coding something for this I wanted to make sure I reported it as a feature request to get a feel for whether or not there is deeper interest in this idea and if it feels like something that should indeed be a part of ImpromptuMVVM.
Oct 26, 2012 Delete comment Project Member jtuley
I think the dispatcher idea is a really good one. The task async stuff, is interesting, I think the backwards compatibility without much overhead could be done with a slight syntax change such as CommandAsync.Save or something to that effect. Would welcome code.

FYI on my github I have my more bleeding edge stuff now. including the solution updated for VS2012 https://github.com/jbtule/impromptu-interface
Nov 3, 2012 Delete comment max.battcher
I forked it on github last weekend and think I actually got this coded. I haven't sent a pull request yet because I think I want to build a simple quick WPF app to test it a bit, but the code is there if you want to see what I've attempted:

https://github.com/WorldMaker/impromptu-interface
Jan 12, 2013 Delete comment max.battcher
Quick update that in the last few weeks I've moving towards a different approach to similar ideas here: I've been working in small amounts of spare time to try my hand at hybridizing ImpromptuInterface.MVVM with ReactiveUI (reactiveui.net)...
Jan 31, 2013 Delete comment max.battcher
I've posted my port of ImpromptuInterface.MVVM on top of ReactiveUI thus far to github: https://github.com/WorldMaker/ReflexUX

There is still a bunch of things on my TODO list and it needs a sample application, but there should be enough code there to get an idea of what I'm trying to do with it. I'd appreciate any feedback you might have.
Jan 31, 2013 Delete comment Project Member jtuley
Wish I was more familiar with ReactiveUI, looks clean, very interested in seeing a sample app! Made some comments on git hub too.
Jan 31, 2013 Delete comment max.battcher
Yes, thanks a lot for the comments. Here's my first crack at a sample app by forking and branching an existing RxUI sample: https://github.com/WorldMaker/RxUI_QCon/tree/reflex

There's still plenty I want to do with this, but I think this shows a good start.

Portable Library

To make a portable library is going to going to be challenging.

First i'm splitting out the features that are easy to make portable. Such as the fun DLR api code and the FSharp code:

Dynamitey and FSharp.Dynamic

Then it's all about splitting out the emit code to platform specific dependencies, and having an easy way for Win8 to pregenerate their proxies (maybe just sample done with scriptcs?).

Then I nead to find a place for a new ImpromptuInterface.MVVM rewrite it to work on all the above portable stuff. (if possible ICustomTypeProvider is missing from PCL)

feature: ActLike convert tuple

It will be nice for legibility if we can use ActLike() method from Tuples, converting this code example from:

var account = new
            {
                Id = "valid_id",
                Name = "valid_name",
                Email = "[email protected]",
                Password = "valid_password"
            }.ActLike<IAccount>();

To this:

var account = (
                Id: "valid_id",
                Name: "valid_name",
                Email: "[email protected]",
                Password: "valid_password"
            ).ActLike<IAccount>();

I am not sure if we are able to do this, because C# has some limitations on using Tuples, but it will be nice if we can have this kind of feature 😍

A CanActLike<TInterface>extension method would be nice for unit testing

Using dynamic proxies opens us up to runtime errors since C# can't type-check when "casting" an object to an interface it doesn't actually support. It would be nice if there were a CanActLike method which would scan an object's type and check to see if it actually supports the methods specified, so that can be unit-tested against.

Sorry if there is such a method already; I searched through Impromptu.cs which seemed to be the logical place for that and didn't find one!

Serialization

More of a question...but can one plug in their own serialization to utilize ActLike? Or does this only work with dynamic objects? I'm asking because I work with XSDs and XML. I can see it works with json and I'm assuming it uses some sort of a serializer.

lock and Dictionary

Not an issue, I was just looking at the code and wondering... is there any specific reason to prefer lock+standard Dictionary over ConcurrentDictionary for _typeHash and _delegateCache in BuildProxy?

Hosting on serveless environments

Hi,
taking into consideration the fact that impromptu-interface uses reflection.emit to generate the proxies, I suppose using this technique on a serverless/microservices environment where services are spawned upon request would not be suggested, as the proxies must be regenerated every time a new instance of the service is started.

So do you indeed discourage the use on such environments ?
Is there any way to cache the proxies between different instances ?

Define proxy methods for out / ref parameters

ParameterBuilder IsIn & IsOut need to be set correctly for functions with out / ref parameters, along with codegen to propagate values back to the caller. eg .ActLike<Microsoft.Office.Interop.Word.Range>()

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.