-
-
Notifications
You must be signed in to change notification settings - Fork 735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a way for modules to add default assemblies and namespaces for the script #1770
Comments
Hmm, if we only could pass the container to the modules when registering. Then you could first resolve the current registered @patriksvensson what do you think about that idea? But in order to do that, we should create our own container abstraction, or else modules needs to take on |
Taking on an AutoFac dependency means locking it to 3.5.2, Cake's referenced version, which means making it incredibly difficult for my module to target netstandard1.6. Container abstraction just needs Resolve and Release, right? |
@mholo65 Why not allow registering a We could change public ScriptConventions(... IEnumerable<IScriptConvention> conventions)
{
...
} |
That's a nicer solution for this particular issue. But, next I will ask to be able to decorate the previous ICakeEngine instance, so @mholo65's solution kills more birds with one stone. Having both would be great too! |
IModule implementations already supports constructor injection of registered dependencies so I don't think this is necessary. To replace a service, register another one of the same service type. The last registered one will always be the one that's used. |
@patriksvensson Ah, I didn't try taking the previous IScriptConventions as a constructor dependency in my ICakeModule implementation! You're right, that should work. |
@jnm2 could you verify that suggested spproach work for you, and if it does please close this issue. Thanks! |
@mholo65 Yes. I'll hopefully get to that tomorrow. |
Confirmed working: internal sealed class SomeCakeModule : ICakeModule
{
private readonly ICakeEngine previousEngine;
private readonly IScriptConventions previousScriptConventions;
public BeforeDependenciesCakeModule(ICakeEngine previousEngine, IScriptConventions previousScriptConventions)
{
this.previousEngine = previousEngine;
this.previousScriptConventions = previousScriptConventions;
}
public void Register(ICakeContainerRegistrar registrar)
{
registrar
.RegisterInstance(new ExtendedCakeEngine(previousEngine))
.As<ICakeEngine>();
registrar
.RegisterInstance(previousScriptConventions.CreateWithAppended(
defaultNamespaces: new[] { typeof(Extensions).Namespace },
defaultAssemblies: new[] { typeof(SomeCakeModule).GetTypeInfo().Assembly }))
.As<IScriptConventions>();
}
} Where I define the extension method internal static class ScriptConventionsUtils
{
public static IScriptConventions CreateWithAppended(this IScriptConventions baseConventions, IReadOnlyList<string> defaultNamespaces, IReadOnlyList<Assembly> defaultAssemblies)
{
return new AppendedScriptConventions(baseConventions, defaultNamespaces, defaultAssemblies);
}
private sealed class AppendedScriptConventions : IScriptConventions
{
private readonly IScriptConventions baseConventions;
private readonly IReadOnlyList<string> defaultNamespaces;
private readonly IReadOnlyList<Assembly> defaultAssemblies;
public AppendedScriptConventions(IScriptConventions baseConventions, IReadOnlyList<string> defaultNamespaces, IReadOnlyList<Assembly> defaultAssemblies)
{
this.baseConventions = baseConventions ?? throw new ArgumentNullException(nameof(baseConventions));
this.defaultNamespaces = defaultNamespaces ?? throw new ArgumentNullException(nameof(defaultNamespaces));
this.defaultAssemblies = defaultAssemblies ?? throw new ArgumentNullException(nameof(defaultAssemblies));
}
public IReadOnlyList<string> GetDefaultNamespaces()
{
return Concat(baseConventions.GetDefaultNamespaces(), defaultNamespaces);
}
public IReadOnlyList<Assembly> GetDefaultAssemblies(DirectoryPath root)
{
return Concat(baseConventions.GetDefaultAssemblies(root), defaultAssemblies);
}
private static IReadOnlyList<T> Concat<T>(IReadOnlyList<T> first, IReadOnlyList<T> second)
{
var r = new T[first.Count + second.Count];
first.CopyTo(r, 0);
second.CopyTo(r, first.Count);
return r;
}
}
} Plus internal static void CopyTo<T>(this IReadOnlyList<T> list, T[] array, int arrayIndex)
{
if (list is IList<T> mutable)
{
mutable.CopyTo(array, arrayIndex);
}
else
{
var count = list.Count;
for (var i = 0; i < count; i++)
array[i + arrayIndex] = list[i];
}
} To Patrik's point, do you guys want to investigate making an easier API so that you don't have to define this extension method and replace |
@jnm2 Perhaps another alternative would be to add a new attribute that could be used to tell cake about stuff a module needs?
|
@patriksvensson I like the syntax. Let's say someone doesn't want to be limited to compile-time constants- would they just do the |
I think I mentioned on some issue we should also honor |
@mholo65 Yes @jnm2 We already use attributes to tell Cake what namespaces to be imported for a Cake alias, so doing the same with modules would keep things consistent. |
@patriksvensson Cool, I like it. Want a PR? |
@jnm2 Sure! Awesome! 👍 |
@patriksvensson I'd like to stay symmetrical with addins and use |
Things are never simple. Currently stuck at #1783 if you would be so kind as to review. =) |
I'd like to be able to have the module add itself to IScriptConventions.GetDefaultAssemblies. You can't do that without registering as the only IScriptConventions instance, and you can't register as the only IScriptConventions instance without losing access to the previous instance of IScriptConventions that you need to delegate to. If two modules need to do this, one will cancel out the other.
That's a general frustration with the registration model, no way to just decorate instances, but what would be nice is some way to supplement the default assemblies and namespaces.
The text was updated successfully, but these errors were encountered: