MEF parts list sometimes empty - mef

I'm currently using MEF and a DirectoryCatalog to load some parts from some extension DLLs. It works for me, and most of the people that use the program, but some users experience the parts not being loaded at all. Collecting some debug information, it seems that MEF does load the DLLs (catalog.LoadedFiles lists them), but that no parts are listed in catalog.Parts.
One user is on XP sp3 and one is on Windows 7, so I don't think that the OS is the problem. Does anyone have some idea of why this would be happening?
The following is the code that actually creates the container, in case it would help with anything.
private static IEnumerable<Task> CreateTypes()
{
CompositionContainer container = GetContainer();
var exp = container.GetExports<Task>();
return exp.Select(e => e.Value);
}
private static CompositionContainer container;
public static CompositionContainer GetContainer()
{
if (container != null)
return container;
DirectoryCatalog catalog = new DirectoryCatalog(ExtensionDirectory, "*.dll");
container = new CompositionContainer(catalog);
return container;
}

(Yes, I'm answering my own question...more than a year later...)
http://mikehadlow.blogspot.com/2011/07/mef-directorycatalog-fails-to-load.html
Basically, because some people downloaded the program using IE then unzipped with Windows Explorer, the DLLs were marked as being from the internet, so MEF refused to load their parts, though they still showed up inside the catalog.
The solution (for my situation at least) was simply to delete the alternate data streams that said that the DLLs were from the internet, as described in the above link.

but the other one is in "C:\Spiele" which sounds like a user-created folder
Reminds me of this:
Assembly Load Issues
In .NET, there are different contexts into which an assembly can be loaded. The default load context is generally the best one to use, but it cannot load assemblies that are not in the application base directory, subdirectories of the application base which are included in the probing path, or the GAC. When using a DirectoryCatalog or passing a path to the AssemblyCatalog constructor, MEF will attempt to load assemblies in the default load context. However, if the assemblies are not in the probing path or the GAC, this will not be possible, and MEF will load them in the load-from context instead.
The load-from context can lead to type identity issues that result in an InvalidCastException, MissingMethodException, or other errors. In order to avoid these issues in a MEF application, you can put any extension directories under the application base directory, and add them to the probing private path in your application configuration file. For other options and more information about assembly loading in .NET, see the Best Practices for Assembly Loading MSDN document.
See the source "How to Debug and Diagnose MEF Failures" for more debugging information and tools.

Related

Prism modules : reference assembly once

EDIT : got it shorter.
We created three modules following the prism doc and our requirements.
We did a horizontal slices with modules.
SharedServices
BusinessLogic
UserInterface
In the UserInterface we are using Syncfusion components and other packages, and It would be great to put everything in the UserInterface module but how can we reference nuget assemblies from that module in the shell (to apply theming for example) to avoid having references in each modules & the shell ?
Should we add nugetpackage to each module and the shell (is it bad... ?) or is it possible to have one module which defines base class referencing external assemblies for example and that would be themable (with ResourceDictionary) & usable in the whole solution (shell & other modules) .
Thanks.
Very broad question, it might well be closed, but I try to give you a few guiding thoughts:
Generally, you either slice horizontally (as you did, UI-module with all the views plus logic-module with all the services) or vertically (as your Product-module suggests: views, view models, services for the product in one module, those for the user in another).
You can do both, but then you should "slice through", so one module for product-ui, one for user-ui, one for product-services, one for user-services... you get the idea. That means a lot of modules, though.
Also, when creating your modules, have an idea of what you want to achieve. Modules can encapsulate components to be reused in another app. Or they can encapsulate exchangeable components, so you could create a car-sharing app today and tomorrow swap out the car-module for a bike-module and have a bike-sharing app. Or they can be used to enforce segregation of code based on risk analysis in a regulated environment. What I'm trying to convey: don't create modules just to have modules, make each module have a defined purpose.
Also, define the interfaces for the modules. I don't like modules to reference each other, as it effectively destroys all segregation that would otherwise be there. Create seperate non-module assemblies that only contain public interfaces. Then make your modules contain the implementations as internal types. In an ideal world, no module assembly contains a public type. The interface-assemblies can be either per module or per consumer or per link between modules (those checked boxes in your N2-chart, you have one, don't you?).
You want to keep the number of modules reasonable, as well as the dependencies between them (not as in "assembly references" but through interface-assembly).
how can we reference nuget assemblies from that module in the shell (to apply theming for example) to avoid having references in each modules & the shell ?
You should separate the "interface" part (e.g. base classes or DTOs, not part of the module) and the actual services part (that's the module). Example: unity has a nuget package for the interfaces (Unity.Abstractions) and one that contains the container implementation (Unity.Container). There's nothing wrong with everyone referencing the interface, basically, that's saying "I want to use that interface".

Entity Framework Connection strings issue

im developing a class library (dll) with visual studio 2012, this library contains a model first created database, with the connection string setted on its app.config file.
Now, im creating a console app (actually a test, but for this its pretty much the same) with an added reference to the dll project.
At first i thought the console app didnt need to know anything about the database, since it was using the dll, however i got a connection string missing error. Fine i added it and it worked, but this isn't what i want, i need the dll to encapsulate all the database related stuff.
Also, what bothers me the most, is that the connection string is also needed on BOTH the dll and the app, even the .mdf file(im using local sql server) generated in the dll/bin/debug folder is needed and copied over to the app/bin/debug folder so i need the file to be on both sides...
How can i make the dll to work by itself, using its own config file and not the app config file? And no, using some kind of service is not an option, it needs to be a dll!
in your database class you can add your connection string like this as base parameter
public class mydb:DbContext
{
public mydb() :base("Server=....")
{
}
}
or you can add your Connection string to app.config and just put its name in base
Example:
public mydb() :base("ConnectionstringName")

GWT: Get constants in server side

I'm trying to get the constants (ConstantsWithLookup) stored in the client side in my server side, but it can't figure out how to do it. I have my constants interface and my constants properties in the same folder.
I've tried tips of other similar threads with no success.
I tried Hermes, gwt-i18n-server, gwt-dmesg, GTWI18N, using a ResourceBundle, trying to get source file properties.
For the first two, it seems that the main reason is the outdated support for the newest GWT version. As for the ResourceBundle, it cannot find the properties file because at deployment, there isn't a properties file, just a Constants.class.
I'm trying to avoid changing my properties file to another location (like /WEB-INF/constants).
I'm using Hermes with GWT 2.5.0.rc1, and it works fine. Usage:
put hermes-1.2.0.jar into war/WEB-INF/lib
Then on the server side write something like
MyConstantsWithLookup my = Hermes.get(MyConstantsWithLookup.class, "de");
String string = my.getString(key);
A properties file MyConstantsWithLookup.properties must exist in the same package as MyConstantsWithLookup.java, even if that properties file is empty (which might be the case if you're using #DefaultStringValue etc.)
Also add MyConstantsWithLookup_de.properties etc.
Make sure, that these properties files are copied next to your classes when compiling. Javac doesn't do that, so it must be done in an additional build step (Eclipse usually does this automatically, but it won't happen by itself when you build e.g. with Ant)
Many build setups will skip the java and properties files from the "client" package when compiling the server side. In that case, put your constants files in the "shared" package (if you have one).

MEF unable to oversrite DirectoryCatalog file. Access Denied

I'm having issues with MEF where I have a DirectoryCatalog and in a later stage want to overwrite the assembly and "refresh" the catalog.
The problem i'm running into is that the file simply is "in use" and I can't overwrite the file. Normaly you are able to overwrite a .Net assembly.
I quess MEF has it in use, but how does this match with Recompilation?!
Here is my code example. Even with local variables the file is still in use.
I've also tried to have the assembly in both application and plugins folder but then the app folder version is used and therefor overwriting does not make a difference.
public RecompilationExample()
{
DirectoryInfo dir = new DirectoryInfo(".\\plugin");
if (!dir.Exists)
dir.Create();
DirectoryCatalog d;
CompositionContainer c;
d = new DirectoryCatalog(".\\plugin");
d.Changed += new EventHandler<ComposablePartCatalogChangeEventArgs>(d_Changed);
c = new CompositionContainer(d);
c.ExportsChanged += new EventHandler<ExportsChangeEventArgs>(c_ExportsChanged);
c.ComposeParts(this);
}
Normaly you are able to overwrite a .Net assembly.
As far as I know, no. A loaded .NET assembly cannot be overwritten. You also can't unload a loaded assembly (except by unloading the entire AppDomain it is hosted in).
What you can do instead is to use shadow copying, i.e. copying the assembly and then loading the copy. You can enable this with the AppDomainSetup.ShadowCopyFiles property. This is typically used in ASP.NET and allows you to overwrite the original file, but not in a way that influences the running process - until you restart it.
See also this other answer I wrote in response to a similar question. Long story short: You can use DirectoryCatalog.Refresh to add new assemblies on the fly, but not to replace or remove them. When you need to replace assemblies, the best solution is to restart your process.

Can CodeDom add Source Code Files to a Project?

I have been using CodeDom to do some code generation. It works great, but I haven't found a way to include the generated source code files in a project. I started using T4 and the T4Toolbox to generate code because it supports integration with project files.
Does anyone know if CodeDom supports this functionality too? I'd consider taking a second look at CodeDom if it only supported this one feature.
Here is an example of how I make a source code file with CodeDom:
protected void CreateSourceFile(CodeCompileUnit codeCompileUnit,
string fileName,
out string fileNameWithExtension)
{
fileNameWithExtension = string.Format("{0}.{1}",
fileName,
CodeProvider.FileExtension);
var indentedTextWriter =
new IndentedTextWriter(new StreamWriter(fileNameWithExtension,
false),
TabString);
CodeProvider.GenerateCodeFromCompileUnit(codeCompileUnit,
indentedTextWriter,
new CodeGeneratorOptions());
indentedTextWriter.Close();
}
That works fine but it just outputs the file to the hard drive somewhere (probably bin folder).
Here is a second example of some code I use with T4, this one specifies the output as part of the project the template is transformed in:
public class RDFSClassGenerator : Generator
{
private readonly string rootNamespace;
private readonly string ontologyLocation;
public RDFSClassGenerator(
string rootNamespace,
string ontologyLocation)
{
this.rootNamespace = rootNamespace;
this.ontologyLocation = ontologyLocation;
}
protected override void RunCore()
{
XElement ontology = XElement.Load(ontologyLocation);
var service = new RDFSGeneratorService(ontology);
foreach (MetaClass metaClass in service.MetaClasses)
{
var rdfsClassTemplate = new RDFSClassTemplate(rootNamespace, metaClass);
rdfsClassTemplate.Output.File = "Domain/" + metaClass.Name + ".cs";
rdfsClassTemplate.Render();
}
}
}
So the T4 code will output the file into the "Domain" folder of my project. But the CodeGen stuff just outputs the file on disk and doesn't update the project file.
Here is a visual:
Yes, it can. Here is how: http://www.olegsych.com/2009/09/t4-and-codedom-better-together/
Short answer is no, but I could be wrong (ever try to prove a negative?)
Your question was a little confusing as CodeDom isn't exactly equitable with T4. T4 templates are a convenient way of generating code files the same way, for example, asp.net generates HTML files, mixing text and code that gets executed to generate a file that is then interpreted by something else (such as a compiler or a browser). CodeDom is usually used to generate assemblies at runtime rather than files, although you can do it (as you have discovered).
While T4 makes it easy to add files to the solution, you can do this with CodeDom as well. I don't believe it supports interaction with the solution directly, but you can manage this using EnvDTE, or the automation model for Visual Studio.
The problem with this is that the automation model isn't easy to work with. EnvDTE is a wrapper around COM classes, which is always fun to code against. Also, you have to be careful when attempting to get the object. The naive implementation will get the object from the first instance of Visual Studio loaded. You have to poll the Running Object Table to find the current instance. Once you have it, you must deal with searching through the dte for the location you're looking for, deal with source control, locked files, etc etc.
Working with it, you start to learn why T4 was created in the first place.
The question you have to ask yourself is, "Does CodeDom give me enough that T4 doesn't to make up for all its shortcomings?"