Vandelay is an add-in to the Fody IL weaving project framework. Vandelay is an Importer\Exporter.
https://www.nuget.org/packages/Vandelay.Fody/
PM> Install-Package Fody
PM> Install-Package Vandelay.FodyVandelay aims to solve the Open Closed Principle from the SOLID principles. Behind the scenes, it uses the Managed Extensibility Framework (MEF) to provide importing\exporting.
However, MEF can be a quite verbose framework, and it may be easy to forget to mark a class as exportable. Vandelay seeks to simplify using MEF.
Vandelay will automatically mark your classes with the appropriate Export attribute.
What you write:
[assembly: Vandelay.Exporter(typeof(IFoo))]
public interface IFoo {}
public class Foo : IFoo {}What gets compiled:
public interface IFoo {}
[Export(typeof(IFoo))]
public class Foo : IFoo {}I have abstract classes which implement the interface type I want to have exported. Will they be exported too?
No, Vandelay only exports instances of classes. Abstract classes will be skipped.
Not a problem. Vandelay first checks whether the type is already exported and only exports unexported classes.
Vandelay will automatically add the code to import a specified type.
What you write:
public class SomeClass
{
public void SomeMethod()
{
var foos = Vandelay.Importer.ImportMany<IFoo>("");
}
}What gets compiled:
public class SomeClass
{
public void SomeMethod()
{
var foos = IFooRetriever.IFooRetriever(new object[0]);
}
}
internal sealed class ExportValueProvider
{
private readonly object _value;
ExportValueProvider(object value)
{
this._value = value;
}
public object GetValue()
{
return this._value;
}
}
internal static class CompositionBatchHelper
{
public static CompositionBatch CreateCompositionBatch(object[] exports)
{
var compositionBatch = new CompositionBatch();
for (var i = 0; i < exports.Length; i++)
{
var obj = exports[i];
var type = obj.GetType();
compositionBatch.AddExport(new Export(
AttributedModelService.GetContractName(type),
new Dictionary<string, object>
{
["ExportTypeIdentity"] = AttributedModelService.GetTypeIdentity(type)
}, new Func<object>(new ExportValueProvider(obj).GetValue)));
}
return compositionBatch;
}
}
internal sealed class IFooRetriever
{
[ImportMany(typeof(IFoo))]
private IFoo[] _imports;
private IFooRetriever(object[] exports)
{
using (var aggregateCatalog = new AggregateCatalog)
{
aggregateCatalog.Catalogs.Add(new DirectoryCatalog( // *
Directory.GetParent(new Uri(Assembly.GetExecutingAssembly()
.EscapedCodeBase).LocalPath).FullName));
using (var compositionContainer = new CompositionContainer(
aggregateCatalog, new ExportProvider[0]))
{
compositionContainer.Compose(CreateCompositionBatch(exports));
compositionContainer.ComposeParts(this);
}
}
}
public static IFoo[] IFooRetriever(object[] exports)
{
return new IFooRetriever(exports)._imports;
}
}It allows you to specify file patterns to match when searching the directory for files. Multiple entries are separated by a vertical pipe (|).
For example:
Vandelay.Importer.ImportMany<IFoo>("*.exe|*.dll")changes the Retriever code (above at *) to
var catalogPath = Directory.GetParent(new Uri(
Assembly.GetExecutingAssembly()
.EscapedCodeBase).LocalPath).FullName;
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(
catalogPath, "*.exe"));
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(
catalogPath, "*.dll"));This allows you to specify objects you want your imported classes to use.
For example, given the following
public class FooWithImport : IFoo
{
[Import]
Bar MyBar { get; set; }
}
public class Importer
{
public IReadOnlyList<IFoo> Imports { get; } =
Vandelay.Importer.ImportMany<IFoo>("*.dll", new Bar());
}the Imports collection will contain a FooWithImport object with the MyBar property filled in.
-
Objects which contain a string in the constructor aren't currently working when you inline the object array. The current work-around would be to create the array before the call to ImportMany such as:
var exports = new object[] { "string export", 42, new Bar() }; var imports = Vandelay.Importer.ImportMany<IFoo>("*.dll", exports);
-
You cannot currently specify the contract name or type, so if you had an import expecting a type of IBar you would have to explicitly specify the contract name and type, such as:
[Import("Fully.Qualified.Namespace.Bar", typeof(Bar))] IBar MyBar { get; set; }
-
If you're using .Net Core and your assembly's runtime path contains a
#, Vandelay won't be able to find the assemblies to scan.
No.