It seems that Flex 4.5 can not compile my old AIR applications that implement the IDisposable interface. What? Why? And how should memory management be done from now on?
I've searched the Adobe site, various forums and of course googled the net up and down.
Cheers
I can't say I've ever seen a class called IDisposable in the API even after looking at all the docs and searching online. I mean there are tons of interfaces for it, but it's not in the API. I believe you're just missing a file or a reference to a library that had an IDisposable so that you can programically 'destroy' objects and leave it for the GC to collect.
Here's an easy implementation of the pattern:
public interface IDisposable {
function dispose():void;
}
public class MyComponent implements IDisposable {
// Implements dispose method that must be called just before
// releasing a MyComponent object
public function dispose():void {
// Clean up:
// - Remove event listeners
// - Stop timers
// - Set references to null
// - ...
}
...
}
This is a good pattern for follow, but often times isn't needed if each Flex component is encapsulated and uses a good component lifecycle practice.
Related
I'm trying to get an understanding of which concrete types are providing the implementations of interfaces in an IOC (dependency injection) container. My implementation works fine when there are no delegates involved. However, I'm having trouble when a delegate method is passed as the type factory, as I can't get Mono.Cecil to give me the concrete type or a method reference to the factory back. I'm specifically in this case trying to build a component that can work with the IServiceCollection container for .Net ASP.Net REST APIs. I've created a 'minimised' set of code below to make it easy to explain the problem.
Consider the following C# code:
interface IServiceProvider {}
interface IServiceCollection {}
class ServicesCollection : IServiceCollection {}
interface IMongoDBContext {}
class MongoDBContext : IMongoDBContext
{
public MongoDBContext(string configName) {}
}
static class Extensions
{
public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
{
return null;
}
}
class Foo
{
void Bar()
{
IServiceCollection services = new ServicesCollection();
services.AddSingleton<IMongoDBContext>(s => new MongoDBContext("mongodbConfig"));
}
}
When successfully locating the 'services.AddSingleton' as a MethodReference, I'm unable to see any reference to the MongoDBContext class, or its constructor. When printing all the instructions .ToString() I also cannot seem to see anything in the IL - I do see the numbered parameter as !!0, but that doesn't help if I can't resolve it to a type or to the factory method.
Does anyone have any ideas on how to solve this?
Most likely your code is looking in the wrong place.
C# compiler will try to cache the conversion of lambda expression -> delegate.
if you look in sharplab.io you'll see that the compiler is emitting an inner class '<>c' inside your Foo class and in that class it emits the method '<Bar>b__0_0' that will be passed as the delegate (see opcode ldftn).
I don't think there's an easy, non fragile way to find that method.
That said, one option would be to:
Find the AddSingleton() method call
From there start going back to the previous instructions trying to identify which one is pushing the value consumed in 1 (the safest way to do that would be to consider how each instruction you are visiting changes the stack). In the code I've linked, it would be IL_0021 (a dup) of Bar() method.
From there, do something similar to 2, but now looking for the instruction that pushes the method reference (a ldftn) used by the ctor of Func<T, R>; in the code linked, it would be IL_0016.
Now you can inspect the body (in the code linked, Foo/'<>c'::'<Bar>b__0_0')
Note that this implementation has some holes though; for instance, if you call AddSingleton() with a variable/parameter/field as I've done (services.AddSingleton(_func);) you'll need to chase the initialization of that to find the referenced method.
Interestingly, at some point Cecil project did support flow analysis (https://github.com/mono/cecil-old/tree/master/flowanalysis).
If you have access to the source code, I think it would be easier to use Roslyn to analyze it (instead of analyzing the assembly).
I have a middleware library I intend on using in multiple projects. The middleware itself looks something like:
public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk)
{
this.next = next;
this.logger = logger;
this.sdk = agentSdk;
this.sdk.Init();
...
}
Thanks to DI, I can simply inject my logger:
// Would rather this class be internal...
public class Sdk: ISdk
{
private ILogger<Sdk> logger;
public Sdk(ILogger<Sdk> logger)
{
this.logger = logger;
}
public void Init() {
this.logger.Info(...) // Do some logging
}
The downside to this is my class needs to be registered in every ASP.Net project's Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISdk, Sdk>();
Is the best/only route? Every time I want to inject a logger into a class, I need to register that class for DI in my composition root?
There is nothing wrong in having the consumer of your library compose the dependencies for this library in the composition root. That's how dependency injection works. You could of course provide some default implementations and a custom extension method that would register those default implementations into the DI and then let the consumer simply call your extension method.
There are a few things that I feel need clarification here:
Dependency injection/inversion of control
To understand what is the benefit of dependency injection(DI) it is better to look at the principle of inversion of control(IoT) that DI implements.
In your case you want SdkMiddleware class to contain a reference to ILogger implementation. The simplest way to do this is for SdkMiddleware class to create an instance of a class that implements ILogger interface. The downside of such approach is that SdkMiddleware needs to know which class implements ILogger interface and how to instantiate it. In other words, SdkMiddleware has control over the creation of ILogger object. The inversion of control happens when the responsibility of knowing which class implements ILogger and how to create an instance of it is taken away from SdkMiddleware to some other class (dependency container in DI) and the instance if it is given to SdkMiddleware to use (through injection in DI). In this case the control over the creation of ILogger object is outside of SdkMiddleware. Since this changes the direction of control, it is called "Inversion of control".
The benefit of this approach is when you will need to provide another implementation of ILogger or change the way you create an instance of that class, you don't need to change SdkMiddleware at all.
Bootstrapping
So now that we clarified why we are using DI, lets take a look at what do we need to actually use it.
The object that creates all instances, controls which object is injected into which and gives away ready to use objects is usually called DI container or IoT container. In asp.net core "IServiceCollection services" is used as such a container. But it still needs to know how to create objects and which implementation to inject for which interface. This is where bootstrapping comes in.
In a bootstrapper class or method you need to specify how objects are built from classes and how classes relate to interfaces. As an example of the former, imagine that you need to pass a connection string for a database from your configuration to a class that creates a db connection. As for the latter, that is exactly what your line "services.AddTransient()" does.
The answer
I am sorry it took so long to get to the actual answer for your question but I wanted to provide some overview first.
Do you need to specify a relation between a class and an interface to inject logger into your class? No. Your class may not even have an interface to begin with and DI container will inject all the dependencies in it by default if you ask for an object of a class instead of an instance of an interface. You can also use or define some convention over configuration solution so that binding of classes and interfaces will happen automatically.
The bottom line is that registration of a class and the actual injection are not connected. But the code you provided is the default way to do this.
In my point of view it is a little confusing how to resolve dependecies in XLabs.
According to the sample project here is how I register the dependencies (simplified):
1) Platform dependent in MainActivity.cs:
private void SetIoc()
{
var resolverContainer = new SimpleContainer();
resolverContainer.Register<IMediaPicker, MediaPicker>();
Resolver.SetResolver(resolverContainer.GetResolver());
}
2) Platform independent in App.cs:
public App ()
{
DependencyService.Register<ISettings, Settings>();
DependencyService.Register<FooViewModel>();
}
Now, it is rather difficult to resolve the dependencies. The expected way would be resolving by constructor injection, which ends in exceptions:
public FooViewModel(IMediaPicker picker) {} // Exception
public FooViewModel(ISettings settings) {} // Exception
Another, but not optimum way is to resolve by DependencyService / Resover. But here I need to know which I have to use:
public FooViewModel()
{
_picker = Resolver.Resolve<IMediaPicker>();
_settings = DependencyService.Get<ISettings>();
}
This all seems not optimal for me (e.g. for unit testing). Is there a way to unify the whole resolving process, in the best case via constructor?
Theres not reason not to place your implementations in your constructors and pass them down the stack. Define your Interface in your PCL implement it in your Android or IOS specific projects and pass it into the PCL on you APP constructor. It will work fine.
The problem arises though when you start to have more then about 3 interfaces you want to be platform specific. When the constructor of your App starts to get longer then the constructor of your MainPage you might start looking for other options.
DependencyService is a simple low ball container that Xamarin Forms offers you. You can use it for platform specific or within the PCL. It takes simple forms. You register your interface and the implementation you want to use for it and then you can retrieve a new instance of the implementation anywhere in your PCL or platform specific code. It's simple to use.
Register with
DependencyService.Register<IMyInterface,MyClass> ();
Get an instance of MyClass just call
IMyInterface me = DependencyService.Get<IMyInterface> ();
and me will be a brand new baby MyClass.
You could also call it in your Platform specific code.
DependencyService.Register<IMyInterface,MyAndroidVersion> ();
and then in your PCL
IMyInterface me = DependencyService.Get<IMyInterface> ();
would give you MyAndroid version.
XLabs Container works the same way just gives you more options. You don't have to use both in fact I'd recommend against it. Pick one of the three options and use it. If you start with the first two you could eventually outgrow them so XLabs might be the best choice.
Personally I use the SimpleIOC container from MVVMLight. But they are all basically the same thing just with a few different bells and whistles.
I have implemented IAuthenticationFilter to create a custom one. in the constructor I use structureMap to get instance of my IUnitOfWork. this authentication logic is to check user status in the database and ....
IUnitOfWork uow;
public CustomAuthenticatationAttribute()
{
this.uow = ObjectFactory.GetInstance<IUnitOfWork>();
}
I have configured structureMap to serve IUnitOfWork HttpContextScoped.
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new MyDbContext());
but then something strange happened. I deleted the user in one action, but when the AuthenticationFilter is executed on another action, the instance of unitOfWork still returns the user ! I searched the web for hours and I come to this :
Are ActionFilterAttributes reused across threads? How does that work?
in short , it says that Filters are cached and used across requests !
Now I'm confused . how to deal with this ? shall I give up using unitOfWork and get back to using(var context = ....) ? or there is a correct way of using unitOfWork inside Filters .
I found a solution here
https://gist.github.com/ivanra/9019273
It replaces the DefaultFilterProvider and I prefer to avoid that if possible.
The solution you found with suppressing caching in the FilterProvider is actually the same solution that the MVC integration libraries for both Autofac and Simple Injector use.
But the caching behavior of attributes is just one of the many reasons why doing dependency injection in attributes is actually a bad idea.
The best solution is IMO to move to passive attributes if you can, or at least encapsulate the attributes logic and its dependencies into a component and don't do anything more than resolving and executing that component in the OnActionExecuting method. For instance:
public class CustomAuthenticatationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var action =
ObjectFactory.GetInstance<IActionFilter<CustomAuthenticatationAttribute>>();
action.OnActionExecuting(this, context);
}
}
I am trying to use the Unity event aggregator to do messaging between various parts of an application. Currently, this is the only feature of the Prism framework that I would like to use. I am having some trouble understand basic concepts I think.
My goal is in some places to be able to broadcast a certain event, and then pick that event up in other places. The code that I have found to do that requires access to the Unity Container, which from what I can tell requires configuration in a bootstrapper and the bootstrapper needs to instantiate the window. This seems like a lot of extra hoops to jump through in my situation of just wanting to use the event aggregator.
Can somebody point me in the right direction for the bare minimum code to use the event aggregator and nothing else from Prism?
It turns out all that needs to be done is instantiate an instance of the EventAggregator class that prism provides. No container needed. I did it in a singleton. Here's the code I used:
public class MyEventAggregator
{
private static MyEventAggregator instance = new MyEventAggregator();
public static MyEventAggregator GetInstance()
{
return instance;
}
private EventAggregator _Aggregator;
public EventAggregator Aggregator
{
get
{
return _Aggregator;
}
}
private MyEventAggregator()
{
_Aggregator = new EventAggregator();
}
}
You do not need to initialize your Unity Container in your bootstrapper and the bootstrapper is not required to instantiate the window. You can initialize your Unity container in any class you want. The only problem is to spread the Unity instance over your application to have an accessible reference where it is needed.