polterguy / lizzie

A script language for .Net and the CLR
https://ainiro.io/
MIT License
190 stars 27 forks source link

Lizzie and DI #3

Closed LeslieMurphy closed 5 years ago

LeslieMurphy commented 6 years ago

Could I use Lizzie where the .net CLR functions to be accessed by the script are provided by dependency injection in .Net Core?

polterguy commented 6 years ago

Not sure I entirely understand your question, but I have been thinking about using Lizzie as an alternative to DI myself previously. This of course would require some mechanism that creates instances of my types exposed as Lizzie function(s). I have never tried this myself, but you can exchange the DI classes used by .Net Core to create instances. Otherwise using for instance Ninject as an alternative DI lib to the one that comes out of the box wouldn't be possible, right? I don't know the exact semantics of how to accomplish this though, but it's definitely an interesting use case :)

The really nifty feature with such a thing, is the ability to provide richer code during object instantiation than what a pure DI library could provide normally, and completely removing all dependencies upon statically compiled code, resulting in that you could simply edit a simple script file (Lizzie file), to change your implementation classes for your DI interfaces ...

Let me know if my answer is not relevant to your question, and/or what you find out yourself as you try this out, since I would be interested in knowing these things myself too ...

polterguy commented 6 years ago

PS, maybe if you Google "How to use Ninject as DI library with .Net Core" or something, you'd find out how to accomplish this, since I assume the process would be very similar ...

LeslieMurphy commented 6 years ago

Thanks for considering this.

What I was thinking of is how to bind Lizzie code to services that come into my code via Interfaces that get injected. The place in my existing ASP.NET Core codebase where I would want to use Lizzie has all of the underlying business logic services provided via the built-in DI mechanism.

For example, .NET automatically injects interfaces into the controllers.

public TransformationController(ILogger<ProjectDataFileManagementController> logger, IProjectDBManager dbManager, IEngineServices engineServices, IProjectActivityLogger projectActivityLogger) I should be able to include the Lizzie logic into my core service layer (EngineServices), and then the scripts can have access to methods I bound directly to existing classes. I was just wondering if it could use an interface as well.

There is a way to swap out the DI built into .NET Core for something else.

See https://asp.net-hacker.rocks/2017/05/08/add-custom-ioc-in-aspnetcore.html

polterguy commented 6 years ago

You can use polymorphism on the methods you bind towards, since the Bind attributes are inherited. This would probably allow you to do what you want to accomplish. However, you'd probably want to bind towards your type that is your implementation, unless you'd want to create an additional interface containing your bound methods, and then bind towards this interface.

However, as I understand more of your particular problem, I realise that there should probably have been a way to dynamically bind towards a type, implying a Binder class that is not a generic, but rather takes a type as an argument, since I assume your problem is that you don't know the type you bind towards during compile time, right ...?

You could probably implement this yourself if you want to, but I assume it would require modifying Lizzie itself, and create a Binder class that is not a generic class, but rather takes the type as an argument to its (for instance) constructor, etc ...

The code is very clean though, and doing this would probably be quite easy - Until I get time to implement something similar myself in the core of the lib. If you do this, and your code is clean and high quality, feel free to send me a pull request :)

polterguy commented 6 years ago

I'll put this up on my todo (Type parameter to an alternative Binder) but it'll have to wait a while, since I'm literally swamped in my day job at the moment ... :)

polterguy commented 5 years ago

Hi Lesley, I did some pretty nifty changes this weekend, which can be found in the repo, but allowing for binding towards object.GetType(), which I assume is what you would want, right? - Is a larger job, and I'll need toset aside probably half a weekend to only focus on that, since it would require some fairly larger changes, and I don't want to impose breaking changes unless I have to, and I know I can avoid them ...

I'll leave this open for the moment though to serve as a TODO for myself and I'll investigate it possibly next weekend or something ... (I am swamped at my dayjob ...)

polterguy commented 5 years ago

Hi Leslie,

I have started implementing basic support for binding towards an "unknown type", which allows you to bind towards an instance of an interface, where you don't actually know the concrete type that your Lizzie code should be bound towards. This should make it more "DI friendly" for your needs. However, it's not entirely done quite yet, and I am not sure if I can manage to do it, without enforcing the implementation to somehow supply its own BinderBase type.

I'll play around with it more during the weekend, but you can checkout the code in the latest master branch if you like. Suggestions for simplifications are gratefully appreciated.

One breaking change so far, which is that in order to be able to pull this through, I have less "type information" during cloning of binders, which forces client code to do one cast if it consumes the LambdaCompiler.Compile override that takes an explicit binder, which I suspect extremely few people are actually using, since it's only necessary as an optimization feature, and only relevant if you've invoked Clone on your Binder instrance, and you want to pass in the results of your Clone operation.

This (tiny) breaking change, which I suspect nobody will even notice in fact, was necessary since the Clone method's signature no longer is the most derived type. I suspect nobody will even notice though, and I might be able to even remove this breaking change, once get to fry some more neurons on the problem ... ;)

Code is not entirely done yet, but it's a basic implementation, of something that might work for your scenario. I'll do more work on this during the weekend, since I think this is a "killer feature" myself :)

polterguy commented 5 years ago

Done!!

Dependency Injection is here ... ;)

Should be available in NuGet within an hour or two ...

polterguy commented 5 years ago

PS, that was a hard one ...!! :D