Comments (7)
@Lele0037 That's failing up above because the ProjectB assembly cannot be found in your application when you run. Very easy fix is to make the direct reference to ProjectB from your application and go on with your day. Otherwise, I guess you could try to manually load the ProjectB assembly in your application before using Marten so that Assembly.Load() can function correctly.
from marten.
Hi @jeremydmiller , thank you for your response. Unfortunately, having ProjectB referenced in ProjectA is kind of a deal breaker: the whole purpose of this project is having ProjectA so that it does not know in advance which modules it will use (all the assemblies are loaded dynamically from a directory, so ProjectA cannot reference ProjectB).
I also tried adding an assembly pre-loading phase in Program.cs, like this:
var assembly = Assembly.LoadFrom("<path to dll>\\ProjectB.dll");
assembly.CreateInstance("ProjectB");
but it throws another error:
[2023-05-03T12:49:46.503Z] Error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ArgumentException: ParameterExpression of type 'ProjectB.Test' cannot be used for delegate parameter of type 'ProjectB.Test'
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters, String paramName)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
at Baseline.Expressions.LambdaBuilder.SetProperty[TTarget,TProperty](PropertyInfo property)
at Baseline.Expressions.LambdaBuilder.Setter[TTarget,TMember](MemberInfo member)
at Marten.Internal.Storage.DocumentStorage`2..ctor(StorageStyle storageStyle, DocumentMapping document)
at Marten.Internal.Storage.QueryOnlyDocumentStorage`2..ctor(DocumentMapping document)
at Marten.Generated.DocumentStorage.QueryOnlyTestDocumentStorage1398299618..ctor(DocumentMapping document)
at Marten.Generated.DocumentStorage.TestProvider1398299618..ctor(DocumentMapping mapping)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
--- End of inner exception stack trace ---
at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
at System.Activator.CreateInstance(Type type, Object[] args)
at Marten.Internal.CodeGeneration.DocumentProviderBuilder.BuildProvider[T]()
at Marten.Internal.ProviderGraph.StorageFor[T]()
at Marten.Internal.Sessions.QuerySession.StorageFor[T]()
at Marten.Internal.Sessions.DocumentSessionBase.store[T](IEnumerable`1 entities)
at Marten.Internal.Sessions.DocumentSessionBase.Store[T](T[] entities)
at ProjectB.Component1.SaveDoc() in <my path>\Component1.razor:line 18
at ProjectB.Component1.SaveDoc() in <my path>\Component1.razor:line 21
at ProjectB.Component1.<BuildRenderTree>b__0_0() in <my path>\Component1.razor:line 10
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
It seems that it has been able to load the assembly, but the loaded one is not compatible with the one it should be using for creating the document.
from marten.
You're in an older version, so the dependencies have changed underneath you. If you move up to Marten 6, I guess you could try a pull request to JasperFx.RuntimeCompiler's version of AttachAssembly() to try to find the assembly a different way than by name as it is today.
from marten.
@jeremydmiller I was already using version 6 actually. I tried implementing the following before setting Marten's IDocumentStore singleton:
var assemblyGenerator = new AssemblyGenerator();
assemblyGenerator.ReferenceAssembly(projectBAssembly);
var rules = new JasperFx.CodeGeneration.GenerationRules()
{
TypeLoadMode = TypeLoadMode.Dynamic
};
assemblyGenerator.Compile(new JasperFx.CodeGeneration.GeneratedAssembly(rules));
I don't know if I'm using JasperFX right (I noticed that the AttachAssembly method was located in the Compile method I'm using above), but I'm still getting the same error (it's not able to find ProjectB assemblies).
from marten.
So that's what I meant for you to try, but it would need to be applied at the time Marten is trying to do the code compilation. So how are you dynamically discovering your extension assemblies again? I might have to ask you to create a repro project to know how to address this.
from marten.
Every "module" (i.e. every project with its own assembly) contains an object which implements an interface IModule
(its actual structure does not matter). Once these helpers methods are defined,
public static List<Assembly> GetAssemblies(string? path, bool iterate = false)
{
List<Assembly> allAssemblies = new List<Assembly>();
var files = Directory.GetFiles(path ?? "", "*.dll", iterate ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
foreach (string dll in files)
{
allAssemblies.Add(Assembly.LoadFile(dll));
}
var returnAssemblies = allAssemblies.Where(w => w.GetTypes().Any(a => a.GetInterfaces().Contains(typeof(IModule))));
return returnAssemblies.ToList();
}
public static List<IModule> GetModules(string? path, bool iterate = false)
{
var modules = new List<IModule>();
var assemblies = GetAssemblies(path, iterate);
var types = assemblies.SelectMany(a => a.DefinedTypes.Where(x => x.GetInterfaces().Contains(typeof(IModule))));
foreach (Type implementation in types)
{
if (!implementation.GetTypeInfo().IsAbstract)
{
var instance = Activator.CreateInstance(implementation) as IModule;
modules.Add(instance);
}
}
return modules;
}
I execute them in my Program.cs
as follows:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
string modulesPath = "<path where modules are located>";
var modules = GetModules(modulesPath, true); // we look for our assemblies here
foreach (var module in modules)
{
// objects that implement IModule do their stuff
}
builder.Services.AddMarten(options =>
{
options.Connection("<my connection string>");
options.AutoCreateSchemaObjects = AutoCreate.All;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.MapControllers();
app.Run();
}
}
Hope that's clear enough.
from marten.
Hi again,
I finally made it work. I think I know what I was doing wrong: the assemblies were actually loaded twice by mistake. The first assembly load was taking place as above, in the Assembly.LoadFrom("<path to dll>\\ProjectB.dll");
bit. However, in my Blazor project I was also loading the assemblies here:
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="_assemblies">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
@code {
private List<Assembly> _assemblies = new();
protected override void OnInitialized()
{
_assemblies = // here the assemblies where loaded for the second time by mistake, instead of being fetched from memory
base.OnInitialized();
}
}
This was causing the error I reported in my second response. Now everything works fine.
Thank you very much for your help.
from marten.
Related Issues (20)
- Proposal: `Events.FetchForWriting` that works with async projections HOT 3
- [7.0.rc2] Count Distinct throws error HOT 2
- ApplyEventException can leak event data to logs HOT 1
- [7.0.rc2] Variables passed into linq expressions are not being evaluated HOT 1
- Allow combining ordering with dynamic properties and case insensitivity
- Re-examine the initial high water detection in rebuild
- CAST operator missing in generated SQL HOT 5
- Expected version check doesn't work if the stream doesn't exist yet HOT 2
- FlatTableProjection doesn't play nice with AssertDatabaseMatchesConfigurationAsync HOT 2
- NodaTime projection deserialization exception HOT 1
- Marten version 6.4.1 has not been published to NuGet HOT 1
- Fix NodaTime Select(Instant) serialization. Again. HOT 1
- [BUG] Schemas not autoregenerate in development (or even in prod) HOT 1
- Sample for CustomGrouper is not robust
- NpgsqlDataSource - System.ObjectDisposedException : The semaphore has been disposed. HOT 2
- MultiStreamProjection - Identity does not support IEvent<TEvent> as identity source
- MultiStreamProjection - as async projection does not execute apply method when a lot of pending events HOT 4
- Overhaul Command Execution Pipeline HOT 6
- MultiStreamProjection is not supported with QueryAllRawEvents().AggregateTo<>()
- QueryAllRawEvents().AggregateTo() does not set document Id field
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from marten.