Windsor Fluent Registration - All types in an assembly - castle-windsor

I wanted to use the fluent interface in Castle Windsor. Since this isn't available in the "release" binaries for .NET 2.0 I compiled from trunk, which is reported to be fairly stable. I compiled just:
Castle.Core.dll
Castle.DynamicProxy.dll
Castle.MicroKernel.dll
Castle.Windsor.dll
This should be all that is necessary for what I need it for but things aren't working as expected. I have an assembly collection which I iterate through and attempt to load all types contained within each assembly using the following code:
var container= new WindsorContainer();
foreach (var assembly in _assemblies)
{
container.Register(AllTypes.FromAssembly(assembly));
}
I stepped through the code with a debugger. _assemblies has 2 assemblies in it. Each assembly has numerous types defined in it. The loop iterates twice without error but when it completes container is still empty.
Update:
A little clarification. The latest binaries do have the fluent interface, however they target the .NET 3.5 framework. I am working with .NET 2.0. The latest binary release to support .NET 2.0 was RC3.

The Register(AllTypes... syntax is only the start - you have to tell Windsor what it is that you want to register.
For example to get all Controllers:
container.Register(AllTypes
.FromAssemblyContaining(representativeControllerType)
.BasedOn<Controller>()
.Configure(reg => reg
.LifeStyle.PerWebRequest));
Here's another example that registers by following the convention that all classes whose name ends in 'Service' should be registered:
container.Register(AllTypes
.FromAssemblyContaining<ConfigurationService>()
.Where(t => t.Name.EndsWith("Service", StringComparison.Ordinal))
.WithService.FirstInterface()
.Configure(reg => reg.LifeStyle.PerWebRequest));
If you truly want to register all types, you could write a Where clause that always returns true.
By default, Windsor doesn't auto-resolve concrete types.
For more information about fluent registration API read the documentation.

Related

.NET CORE 3 Upgrade CORS and Json(cycle) XMLHttpRequest Error

I had my working project written in asp.net core 2.1 for a long time, but yesterday, I was forced to upgrade it to .net core 3.0 (due to 2.1 cannot call Dll' s which are written in 3.0 already).
With that, a lot of functions were obsolete or already removed. I fixed almost all of it, but one problem with CORS.
Like many people before me, I used:
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
in Configure function. And services.AddCors() in ConfigureServices function.
I was able to fixed this quite easily with setting WithOrigins() or .SetIsOriginAllowed(_ => true) instead of AllowAnyOrigin() which does not work anymore with AllowCredentials().
After that, I was able to start the application and I thought everything is fine, but then I get stuck until now with problem I do not know, how to fix.
I have DB relation N:N and relation table which handle that, that means I have Admin entity with AdminProject list property, then I have AdminProject entity with Admin list and Project list properties and Project entity with AdminProject list property once again.
When I am listing my projects of certain admin, I am returning in Controller this return Ok(projects), where I just use getAll on AdminProject entity and then with Select return only project.
For that, I have to use[JsonIgnore] in project/admin for properties which I do not need to avoid cycling when creating json.
With that said: NOW IN .NET CORE 3.0 AND CORS SETTINGS IT DOES NOT WORK.
I am getting an error:
System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
when debugging in console and error Access to XMLHttpRequest at 'http://localhost:5000/api/project/adminlist/1' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. in WEB browser
I think I tried almost everything with Cors settings etc and I do not know why is this happening now. I also tried to JsonConvert.SerializeObject() before return it ---> return Ok(JsonConvert.SerializeObject(projects)) and this is working, but I am not able (mentally) to do this in every single controllers functions.
Please help! Thanks a lot!
The problem was occurring because in .NET Core 3 they change little bit the JSON politics. Json.Net is not longer supported and if you want to used all Json options, you have to download this Nuget: Microsoft.AspNetCore.Mvc.NewtonsoftJson.
After that in your Startup.cs file change/fix/add line where you are adding MVC (in the ConfigureServices method.
So: here is what I did and what fixed my issue:
services.AddMvc(option => option.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(opt => opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
I hope it will help somebody else.
Cheers!
A couple other things have changed in .net core 3 and now instead of using addMVC you can use addControllers. So your code might look like the follow:
services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Can the ConfigurationAPI in Liferay DXP be used for Plugin sdk portlet?

I have followed given 2 tutorials to use COnfigurationAPI in a Liferay dxp plugins SDK portlet built using Ant/Ivy.
COnfiguration API 1
COnfiguration API 2.
Below is the configuration class used:
package com.preferences.interfaces;
import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition;
import aQute.bnd.annotation.metatype.Meta;
#ExtendedObjectClassDefinition(
category = "preferences",
scope = ExtendedObjectClassDefinition.Scope.GROUP
)
#Meta.OCD(
id = "com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration",
name = "UnsupportedBrowser.group.service.configuration.name"
)
public interface UnsupportedBrowserGroupServiceConfiguration {
#Meta.AD(deflt = "", required = false)
public String displayStyle();
#Meta.AD(deflt = "0", required = false)
public long displayStyleGroupId(long defaultDisplayStyleGroupId);
}
Post following the steps,I am getting the below error:
ERROR [CM Configuration Updater (ManagedService Update: pid=[com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration])][org_apache_felix_configadmin:97] [org.osgi.service.cm.ManagedService, id=7082, bundle=297//com.liferay.portal.configuration.settings-2.0.15.jar?lpkgPath=C:\dev\Liferay\osgi\marketplace\Liferay Foundation.lpkg]: Unexpected problem updating configuration com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration {org.osgi.service.cm.ConfigurationAdmin}={service.vendor=Apache Software Foundation, service.pid=org.apache.felix.cm.ConfigurationAdmin, service.description=Configuration Admin Service Specification 1.2 Implementation, service.id=56, service.bundleid=643, service.scope=bundle}
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
So,does this process need a osgi module as mandatory or can we do it using plusings sdk portlet built using ant as well?
Without disecting the error message Caused by: java.lang.IllegalArgumentException: wrong number of arguments:
The way you build your plugin (Ant, Maven, Gradle, manually) doesn't make a difference, as long as you build a plugin that will be understood by the runtime. aQute.bnd.annotation.metatype.Meta points firmly into the OSGi world, and makes it almost certain that you'll need an OSGi module. You can build this with Ant, of course. Even in Ant you can embed tools like bnd, or you can write the proper Manifest.mf to include in your module manually (just kidding - you don't want to do it manually, but it would work).
Recommendation: Instead of moving everything over: Try to reproduce this with a minimal example in gradle or better Liferay Workspace (which is gradle based), just to get all the automatic wiring in. Check if it makes a difference and compare the generated output from your Ant build process with the workspace output. Pay specific attention to the Manifest.
In order to build the proper Manifest, you want to use bnd - if the Manifest turns out to be your issue: Find a way to embrace bnd - if that's by saying goodby to Ant, or by tweaking your build script remains your decision.

'Application' doesn't exist in System.Windows namespace (in library project)

I'm working on .net standard 2.0 library project for my solution.
It have to include this method:
public Task ShutdownAsync()
{
Application.Current.Shutdown();
}
Problem is it gives me an error:
The name 'Application' does not exist in the current context
It also doesn't exist in System.Windows.
As answers to similar questions suggests I tried to add reference to PresentationFramework. But it isn't on the list.
Looks like it have something to do with the fact I'm doing it in a library project targeted at .net standard 2.0.
Is here any way to add proper reference to this project?
.Net standard 2.0 was the problem.
This class is platform-specific so I should target .Net Platform instead.

How to use mole manually in Visual Studio Express?

I searched for tags "Moles" and "Visual Studio Express", and found no questions. That probably means I'm the only person trying to use Express with Moles :)
In Express, there are no options such as "Add moles assembly", or "Add mscorlib".
I've managed to get the tutorial for the DateTime Y2Kbug working after manually adding a couple of references that would normally be handled by VS. So, that means that I can mole any of the pre-moled stuff in System or mscorlib, which will be useful.
My problem is that I cannot seem to mole any of my own classes or methods in the SUT. I don't believe that the compiler sees any of the .moles file that contains the assemblies to mole.
I proved (?) this by attempting to exclude DateTime from the Y2kbug tutorial, using:
<MoleGeneration>
<Types>
<Remove FullName="DateTime!" />
</Types>
</MoleGeneration>
But the "bug" was asserted as usual :)
Is it possible to generate non-System moles as I need them by using something I saw in this forum: stackoverflow.com/questions/6272217/microsoft-moles-dynamically-instrument
Call Microsoft.Moles.Framework.Moles.MoleRuntime.SetMole(Delegate _stub, object _receiver, MethodInfo method);
If I use the "SetMole" method, does that mean that I don't need "assembly" files which are not seen anyway? If so, would it be possible to give some examples of the use of "SetMole". (I'm not a techie.)
As suggested by Mike Christian, I used moles.exe OrigValueP.dll. This created OrigValueP.Moles.dll in the MolesAssemblies subfolder.
Add OrigValueP.Moles.dll as a reference to the test project.
View OrigValueP.Moles in the Object Browser. I now see MOrigValue.AllInstances. So that's a huge step forward.
However, I don't see any Moles equivalent of my method:
public string TestString() { return "Original value"; }
[Deleted lines relating to the command, "moles.exe OrigValueP.Moles.dll", because MC suggested I'm "attempting to mole the mole assembly".]
So, I have one question (which I will continue to try to answer myself): Why was there no Moled method for TestString()?
The Moles documentation states Moles is compatible with Visual Studio 2008 Professional or Visual Studio 2010 Professional or better. http://research.microsoft.com/en-us/projects/pex/molestutorial.docx
Don't forget that executing the moles compiler via command line requires that you perform compilation in the following order:
1. Target assemblies
2. Moles (against the target assemblies)
3. Test assemblies
The Moles Manual provides the following command line instruction:
http://research.microsoft.com/en-us/projects/pex/molesmanual.docx
Code Generation Command Line The Moles framework includes a command-line application that can generate the code by following the
instructions in .moles files or directly from assemblies. By default,
the command-line tool compiles the stub types and mole types into an
assembly and places it into a MolesAssemblies subfolder. The following
list shows examples of typical usage.
Generate mole types and stub types for a particular
assembly moles.exe assembly.dll Generate mole types and stub types
from an existing .moles file moles.exe assembly.moles Generate
mole types and stub types under a particular namespace moles.exe
assembly .dll /nf:MyNamespace Get detailed help about usage of
moles.exe moles.exe help
[This whole answer has been appended to the original question. Sorry for all the mess.]

MEF: "Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information"

Scenario: I am using Managed Extensibility Framework to load plugins (exports) at runtime based on an interface contract defined in a separate dll. In my Visual Studio solution, I have 3 different projects: The host application, a class library (defining the interface - "IPlugin") and another class library implementing the interface (the export - "MyPlugin.dll").
The host looks for exports in its own root directory, so during testing, I build the whole solution and copy Plugin.dll from the Plugin class library bin/release folder to the host's debug directory so that the host's DirectoryCatalog will find it and be able to add it to the CompositionContainer. Plugin.dll is not automatically copied after each rebuild, so I do that manually each time I've made changes to the contract/implementation.
However, a couple of times I've run the host application without having copied (an updated) Plugin.dll first, and it has thrown an exception during composition:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information
This is of course due to the fact that the Plugin.dll it's trying to import from implements a different version of IPlugin, where the property/method signatures don't match. Although it's easy to avoid this in a controlled and monitored environment, by simply avoiding (duh) obsolete IPlugin implementations in the plugin folder, I cannot rely on such assumptions in the production environment, where legacy plugins could be encountered.
The problem is that this exception effectively botches the whole Compose action and no exports are imported. I would have preferred that the mismatching IPlugin implementations are simply ignored, so that other exports in the catalog(s), implementing the correct version of IPlugin, are still imported.
Is there a way to accomplish this? I'm thinking either of several potential options:
There is a flag to set on the CompositionContainer ("ignore failing imports") prior to or when calling Compose
There is a similar flag to specify on the <ImportMany()> attribute
There is a way to "hook" on to the iteration process underlying Compose(), and be able to deal with each (failed) import individually
Using strong name signing to somehow only look for imports implementing the current version of IPlugin
Ideas?
I have also run into a similar problem.
If you are sure that you want to ignore such "bad" assemblies, then the solution is to call AssemblyCatalog.Parts.ToArray() right after creating each assembly catalog. This will trigger the ReflectionTypeLoadException which you mention. You then have a chance to catch the exception and ignore the bad assembly.
When you have created AssemblyCatalog objects for all the "good" assemblies, you can aggregate them in an AggregateCatalog and pass that to the CompositionContainer constructor.
This issue can be caused by several factors (any exceptions on the loaded assemblies), like the exception says, look at the ExceptionLoader to (hopefully) get some idea
Another problem/solution that I found, is when using DirectoryCatalog, if you don't specify the second parameter "searchPattern", MEF will load ALL the dlls in that folder (including third party), and start looking for export types, that can also cause this issue, a solution is to have a convention name on all the assemblies that export types, and specify that in the DirectoryCatalog constructor, I use *_Plugin.dll, that way MEF will only load assemblies that contain exported types
In my case MEF was loading a NHibernate dll and throwing some assembly version error on the LoaderException (this error can happen with any of the dlls in the directory), this approach solved the problem
Here is an example of above mentioned methods:
var di = new DirectoryInfo(Server.MapPath("../../bin/"));
if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);
var dlls = di.GetFileSystemInfos("*.dll");
AggregateCatalog agc = new AggregateCatalog();
foreach (var fi in dlls)
{
try
{
var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException
agc.Catalogs.Add(ac);
}
catch (ReflectionTypeLoadException ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
CompositionContainer cc = new CompositionContainer(agc);
_providers = cc.GetExports<IDataExchangeProvider>();