DLL dependency not getting copied issue - c#

I'm using VS2015 and have two projects where the child project references DapperExtensions (X--> Y--> DapperExtensions).
Now DapperExtensions seems to have implicit dependency on Dapper.
When I try and use code from Y in X, I get an error regarding Dapper.dll missing.
It seems with dlls being copied to project X debug folder, only DapperExtensions.dll is getting copied but Dapper.dll isn't.
Presumably related to the direct dependency issue identified in stackoverflow already :
Dll not copying to bin folder
So I created some dummy code to reference an arbitrary reference from Dapper but this doesn't seem to lead to the DLL getting copied as per existing suggestions in stackoverflow:
public static void Dummy()
{
Action<Type> noop = _ => { };
var dummy = typeof(Dapper.DbString);
noop(dummy);
}
The only thing I guess left is to add dappper dll reference directly to ProjectX which I really want to avoid.
Any ideas why the dummy reference thing doesn't work?

Related

Is it possible to add a new dependency to a .dll without changing the source code?

I have two dotnetcore2.1 projects. First project calls a method of the second project via reflection.
using System;
using System.Reflection;
namespace experiment1
{
class Program
{
static void Main(string[] args)
{
Type _type = Type.GetType("experiment2.Program");
object _object = Activator.CreateInstance(_type);
MethodInfo info = _type.GetMethod("SecondProjectsMethod");
info.Invoke(_object, new object[]{});
}
}
}
I can't give any reference to the Second Project nor changes its code. How can I make this call successfully without adding a Reference to the First Project? I tried to add records to the first project's deps-file and execute the first program like this:
dotnet exec --depsfile experiment1.deps.json experiment1.dll
It didn't work. Is it even possible to do this by changing deps-file or any other config? Or should I manipulate .dll file somehow? Which direction I should go?
You can manually load the assembly by calling:
Assembly.Load("experiment2");
It should look for the assembly in the current folder, or use the deps file to locate it. After that, you should be able to use Type.GetType just fine.
If you want to specify the full path to the assembly, use AssemblyLoadContext.Default.LoadFromAssemblyPath instead.
You can refer to this page for more information on the different ways of loading an assembly in .net core.

Sharing code between two c# assemblies

1) I have a project called SocketServer in which there is a Class Room, this project is a complied exe and can also be complied as a DLL.
2) In Another project called, lets say, MyGame, there is a class called MyAwesomeGame, in which I need to do something like:
public class MyAwesomeGame
{
public Init(Room room)
{
//I can get data from Room
}
}
Now MyGame Project is compiled into a MyGame.DLL, and is placed somewhere relative to the SocketServer.exe, which at runtime loads MyGame.DLL and Instantiates MyAwesomeGame class and calls the Method Init and passes room as its parameter. Code is SocketServer project is something like:
public class Room
{
private InstantiateGameRoom()
{
//Load External MyGame.DLL Assembly
Task<MyAwesomeGame> task = Task<MyAwesomeGame>.Factory.StartNew(() => (MyAwesomeGame)Activator.CreateInstance(classType, new object[] { this }));
MyAwesomeGame instance = task.result;
instance.init(this);
}
}
So my question is how can I get reference of the Class room in MyGame Project? Should I add reference of my SocketServer Project? and if I do, wont it get complied into my MyGame.dll?
p.s: I also intend to distribute the socketserver.dll as an API to thrid-party users.
You should add the SocketServer's generated dll to the references of the MyGame project. Right click on MyGame, click Add, click References..., in the dialog select Projects and select the SocketServer project.
I believe it is also wise to make sure that SocketServer is a depedency for the MyGame project to make sure SocketServer is built before MyGame.
--edit: please read the comment below that I made after Sushant's clarification. Or go straight to Sid's answer. :-)
I think the proper way to share Models among two or more projects is to extract all the models and relative logics to a separate project.
Then you can reference that project from every project that needs to use that data.
The scenario I am talking about is the following:
ModelsProject (Contains models and business logic)
ProjectA (has a dependency on ModelsProject)
ProjectB (has a dependency on ModelsProject)
Scheme

Recompiling the OpenXmlSdkTool.Core DLL with a anon-method and delegate error

I'm doing research into the OpenXmlSdkTools v2.5 and had a sneak peak inside the OpenXmlSdkTools.Core.DLL and saved it as a c# Project with ILSpy.
While this question is active, here is the OpenXmlSdkTools.Core.DLL as a way to quickly reproduce the problem I'm encountering.
When I tried to compile the single class library project, I get two errors about a missng reference to assembly 'System.Xaml'. eg:
The type 'System.Windows.Markup.IQueryAmbient' is defined in an
assembly that is not referenced. You must add a reference to assembly
'System.Xaml
The type 'System.Windows.Markup.IUriContext' is defined in an assembly
that is not referenced. You must add a reference to assembly
'System.Xaml
So I added the ref.
After that I'm stuck on what I hope is the last compile error and I can't figure it out.
Cannot convert anonymous method to type 'System.Delegate' because it
is not a delegate
type C:\TFS\ABC\src\OpenXmlSdkTool.Core\DocumentFormat.OpenXml.Tools\ApplicationExtensions.cs
10
Here is the code:
using System;
using System.Windows;
using System.Windows.Threading;
namespace DocumentFormat.OpenXml.Tools
{
public static class ApplicationExtensions
{
public static void DoEvents(this Application application)
{
application.Dispatcher.Invoke(DispatcherPriority.Background, delegate
{
});
}
}
}
I'm stuck and puzzled that its a decompiled DLL that should be easy to re-compile again. Do you think by me adding the Xaml reference its caused this problem? And why would I need to add the Xaml reference if the Core.DLL is a class library project and ILSpy didn't included it in the csproj file?
I've looked at all the other questions on here with the same error but none of them really helped.
Update
When you add System.Xaml.dll as reference to your project. The interface is declared there. Here is the doc.
So now I'm in a Catch22, if I add the Xaml dll it will solve the first 2 errors but then it will cause this other error.
After reproducing the issue on my machine, I found this http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/ (referenced from Convert this delegate to an anonymous method or lambda).
Adding a cast to Action solved the issue
application.Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
});
But there are probably other solutions.

Error after deleting an argument (the "method arguments" error)

I have built a class called "MemoryDB" (whose c'tor takes 6 arguments) and created unit-test for her.
Everything was OK until today - I tried deleting one of the arguments, so they remain 5. Even though (after re-building, saving, re-creating the class MemoryDB, etc.), the unit-test does not recognize the change and the error message appears: TimeTable.DB.MemoryDB does not contain a constructor that takes 5 arguments.
I also tried to re-create the unit-test, but for some reason the automatic c'tor it creates is the old c'tor, with 6 arguments.
Have I deleted the argument in a wrong way? How can I fix this? Do other errors in the project might cause this weird problem?
p.s. here is the old c'tor:
public MemoryDB(List<Grade> allGrades, List<Teacher> allTeachers, ForbiddenHours forbiddenHours, List<Group> allGroups, List<List<Teacher>> staffs, List<List<Group>> parallelGroups)
{
CheckParametersValidation(allGrades, allTeachers, forbiddenHours, allGroups, staffs, parallelGroups);
this.allGrades = allGrades;
this.allTeachers = allTeachers;
this.forbiddenHours = forbiddenHours;
this.allGroups = allGroups;
this.staffs = staffs;
this.parallelGroups = parallelGroups;
}
the new c'tor, after deleting "forbiddenHours":
public MemoryDB(List<Grade> allGrades, List<Teacher> allTeachers, List<Group> allGroups, List<List<Teacher>> staffs, List<List<Group>> parallelGroups)
{
CheckParametersValidation(allGrades, allTeachers, allGroups, staffs, parallelGroups);
this.allGrades = allGrades;
this.allTeachers = allTeachers;
this.allGroups = allGroups;
this.staffs = staffs;
this.parallelGroups = parallelGroups;
}
It is difficult to tell why this happens, but there are certain things to look for when troubleshooting such an issue:
If the library was referenced as a DLL, it is possible that the DLL has not been updated.
If that's the case, rebuild the library - if there are any errors, it has not built. Fix the errors.
Once rebuilt, remove the existing reference and re-add it (not strictly needed, you can simply replace the DLL on the file system)
If the library was referenced as a project:
Make sure the library is building without errors.
It is possible that some caching issues are going on. Restart Visual Studio.

Is it possible to use Gephi compiled with IKVM in a website?

I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.
I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:
var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl#8ddb93.
If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.
I have tried a couple of solutions
Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:
var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.
Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.
Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.
I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.
I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.
Update - Answer
Based on the answer from Jeroen Frijters, I resolved the issue like this:
public class Global : System.Web.HttpApplication
{
public Global()
{
var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
var acl = new AssemblyClassLoader(assembly);
java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
}
}
internal class MySystemClassLoader : ClassLoader
{
public MySystemClassLoader(ClassLoader parent)
: base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
{ }
}
The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.
This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.
One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.
For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader

Categories