Load an assembly at runtime - c#

I've used a tutorial (http://support.microsoft.com/kb/837908, method 1) to generate two projects. Project a has a reference to project b.
project a:
new System.EnterpriseServices.Internal.Publish().GacRemove(string.Format(#"C:\Users\[me]\Documents\Visual Studio 2010\Projects\MyAssembly1\MyAssembly1\bin\Debug\MyAssembly1.dll"));
new System.EnterpriseServices.Internal.Publish().GacInstall(string.Format(#"C:\Users\[me]\Documents\Visual Studio 2010\Projects\MyAssembly1\MyAssembly1\bin\Debug\MyAssembly1.dll"));
MyAssembly1.Class1 obj1 = new MyAssembly1.Class1();
MessageBox.Show(obj1.HelloWorld());
project b:
public string HelloWorld()
{
return "1";
}
when I perform the following:
change "HelloWorld" method in project b to return "2" (instead of "1").
build project b
build project a and run it
I get message box with "1" as text, and the GAC doesn't always update itself.
What is the simplest way to update project b and see it on project a?

Firstly, changing the GAC is unlikely to help an already running process. In this specific case, note that JIT happens per-method before the method is executed. Which means MyAssembly1 is resolved and loaded before the remove/install step. However, that doesn't change the fact that this is very unlikely to be a good approach.

Related

System.MissingMethodException after adding a project reference (without using the reference)

I have encountered a strange error that is unexplainable to me.
I have a .NET 6 class library project (A) that has the function:
public async Task ImportDeliveries()
{
try
{
var csvFileProcessor = new CsvFileProcessor();
await csvFileProcessor.ProcessAllAsync(_DeliveryImporter.ImportAsync).ConfigureAwait(true);
}
catch (Exception ex)
{
_TelemetryClient.TrackException(ex);
}
}
It works fine. However, as soon as I add the project reference of another .NET 6 class library (B) to the project, without changing anything else, the function
await csvFileProcessor.ProcessAllAsync(_DeliveryImporter.ImportAsync).ConfigureAwait(true);
fails and throws the following exception:
System.MissingMethodException: 'Method not found: 'System.Threading.Tasks.Task BlobStorageHelper.BlobStorageFolder.MoveAsync(Microsoft.Azure.Storage.Blob.CloudBlockBlob, BlobStorageHelper.BlobStorageFolder)'.'
Can this be caused because (B) contains certain nuget packages?
This behavior is very counterintuitive to me, and I'm not sure where to start looking.
This is probably caused by:
Your project, A, referencing a class library C, in which CsvFileProcessor and BlobStorageHelper.BlobStorageFolder are defined (the latter could also be in a transitive dependency, D).
Project B also references class library C (and/or D), but a different version.
Someone modified, added or removed System.Threading.Tasks.Task BlobStorageHelper.BlobStorageFolder.MoveAsync(Microsoft.Azure.Storage.Blob.CloudBlockBlob, BlobStorageHelper.BlobStorageFolder) in some version of C or D.
You're not properly implementing Semantic Versioning within C or D, so MSBuild is restoring a version of C or D that doesn't contain the required method.
Hence the error.
Takeaway: changing a signature or return type is breaking the ABI (application binary interface), requiring a major version update.
To fix this, you could revert the signature or return type change, and add an overload instead.

C# wrong reference to namespace

Okay this is driving me crazy. I got one almost finished project (which works perfectly) and I wanted to make another one in the same way. The thing is there is a solution with two layers DataAccessLayer and BusinessLogicLayer. Both of these layers have a Model library with all models in the project. I need to convert the model from the first layer to a model of a second layer in the manager library. This works in the finished project I received but I can not manage to make it on mine.
The thing is I can't make the necessary references to work like they do on the finished project. The structure is:
BusinessLogicLayer
--Managers
----Users
--Models
----User
DataAccessLayer
--Models
----User
In the Managers project I have a reference added to DataAccessLayer.Models.
And inside the Users class I got:
using Library.BusinessLogicLayer.Models;
Now in my project this line is red underlined:
Error CS0234 The type or namespace name 'Models' does not exist in the
namespace 'Library.BusinessLogicLayer' (are you missing an assembly
reference?)
I am not even sure how and why this works on that original project. But I can't figure it out so it's working right on my project and the structure is the exact same. Anyone have an idea about this?
EDIT:
Dunno why I didn't upload this earlier. Here is the structure.
https://i.imgur.com/srnySFJ.jpg
EDIT2:
Since it is not quite understandable I uploaded the whole project on github so you can take a closer look at it.
https://github.com/Morsusy2k/Library
And here is the problem:
https://i.imgur.com/DvCvnMA.jpg
From what you described above and from my understanding, it seems that Managers and Models are two different projects. If that is the case, make sure that you add a reference to BusinessLogicLayer.Models in your BusinessLogicLayer.Managers.
If, on the other hand, you have only two projects BusinessLogicLayer and DataAccessLayer then it could very well mean that Library.BusinessLogicLayer.Models is not the name of the namespace.
UPDATE
From the picture that you added, you might need to add a reference to Library.BusinessLogicLayer.Models.Models. You have a folder named Models and a project named Models. Visual Studio automatically generates namespaces based on the Solution name, Solution folders, project name, folders within project.
There were three issues with your code. The first one is that you are supposed to add a reference to Library.DataAccessLayer.Models and not to Library.BusinessLogicLayer.Models. This is due to the fact that you have User in DataAccessLayer.Models and User2 in BusinessLogicLayer.Models.
The other two issues were with the Map method where you are sending incorrect number of arguments to the constructor (you are missing UserId) and the other issues is with your DateOfBirth and DateJoined being in the wrong order in the same method.
using System;
using System.Collections.Generic;
using System.Linq;
using global::Library.BusinessLogicLayer.Models;
using Library.BusinessLogicLayer.Managers.Properties;
using Library.DataAccessLayer.Models; // <-- Add reference to this
namespace Library.BusinessLogicLayer.Managers
{
public class Users2
{
public IEnumerable<User> GetAll()
{
using(DataAccessLayer.DBAccess.Library library = new DataAccessLayer.DBAccess.Library(Settings.Default.LibraryDbConnection))
{
return library.Users.GetAll().Select(user => Map(user));
}
}
private User Map(DataAccessLayer.Models.User dbUser)
{
if (dbUser == null)
return null;
// TODO: Constructor is missing a paremeter. I'll add a temporary one
int tempUserId = 0;
User user = new User(tempUserId, dbUser.Name, dbUser.UserName, dbUser.Password, dbUser.Email, dbUser.DateJoined, dbUser.DateOfBirth) // <-- The last two params are in the wrong order
{
Id = dbUser.Id
};
return user;
}
private Library.DataAccessLayer.Models.User Map(User2 user)
{
if (user == null)
throw new ArgumentNullException("user","Valid user is mandatory!");
return new DataAccessLayer.Models.User(user.Id,user.Name, user.UserName, user.Password, user.Email, user.DateJoined, user.DateOfBirth);
}
}
}
Also, regarding the last screenshot that you provided, you do not have Library.BusinessLogicLayer.Models2 namespace. Remove number 2 to get it to work.
As I don't have permission to update your repo with the fixed code, you'll have to fix it manually based on my answer. Otherwise, let me know so that we see how I can push the code back.
There are a few things you could try:
This error could be appearing within BusinessLogicLayer because DataAccessLayer failed to build. Try building DataAccessLayer by itself to see if you get a different error.
The references might be "added", but you might not be referencing the correct DLL or version for some reason. Check your .csproj files manually to ensure all references and versions are correct, have the right hint paths, etc. If you have any config files, you should also review them to ensure there are no version conflicts.
In addition to checking the references, it is possible to add if-then and switch case logic inside of the .csproj files. This is an MSBuild feature that Visual Studio doesn't support through its GUI, so you may need to copy/update this logic manually in your current .csproj files if any existed.
Check your default namespaces in project properties to see if they are the same as your old project. If you added new files since you moved to this project, they may have been inadvertently added with the wrong namespace and that namespace may be causing a conflict. You could also try using global::Library.BusinessLogicLayer.Models; to see if that fixes or changes the error message or at least if Intellisense is picking the namespace up.
If that doesn't work, review all of your namespaces in all .cs files to see if you have any that have gone rogue.
Since your Models namespace has the problem and you have 2 of them with the same name, try temporarily renaming one of them (yes, every .cs file in one of the projects) to Models2 to see if it provides a clue (such as the error going away or changing).

How to use class from other files in C# with visual studio?

I am a newbie of C# and MS visual studio, and I want to use the C# class which defined in another file, but can't get it work.
Here is the program.cs(and why can't I rename that file ?)
using System;
namespace TestCSharp2
{
class Program
{
static void Main(string[] args)
{
Class2 class2 = new Class2();
// here the IDE will complain that cant find namespace or balabala..
class2.setValue(10);
Console.WriteLine(class2.getValue().ToString());
Console.ReadKey();
}
}
}
And here is the Class2 that I want to use in file Class2.cs:
namespace TestCSharp2
{
class Class2
{
int i;
public void setValue(int i)
{
this.i = i;
}
public int getValue()
{
return this.i;
}
}
}
Should I #include or something? isn't use namespace enough?
As some guys asked if they are in the same assembly/same project, I presume they were, because here is the procedure how they are created:
A new project using the template of Console C# Project, then the program.cs was created by default.
The Class2.cs was created with [File] -> [New] -> [File] -> [C# class] and saved in the same folder where program.cs lives.
To be honest, I don't know if they are in same assembly / same project, but I guess they were.
According to your explanation you haven't included your Class2.cs in your project. You have just created the required Class file but haven't included that in the project.
The Class2.cs was created with [File] -> [New] -> [File] -> [C# class] and saved in the same folder where program.cs lives.
Do the following to overcome this,
Simply Right click on your project then -> [Add] - > [Existing Item...] : Select Class2.cs and press OK
Problem should be solved now.
Furthermore, when adding new classes use this procedure,
Right click on project -> [Add] -> Select Required Item (ex - A class, Form etc.)
Yeah, I just made the same 'noob' error and found this thread.
I had in fact added the class to the solution and not to the project.
So it looked like this:
Just adding this in the hope to be of help to someone.
It would be more beneficial for us if we could see the actual project structure, as the classes alone do not say that much.
Assuming that both .cs files are in the same project (if they are in different projects inside the same solution, you'd have to add a reference to the project containing Class2.cs), you can click on the Class2 occurrence in your code that is underlined in red and press CTRL + . (period) or click on the blue bar that should be there. The first option appearing will then add the appropriate using statement automatically. If there is no such menu, it may indicate that there is something wrong with the project structure or a reference missing.
You could try making Class2 public, but it sounds like this can't be a problem here, since by default what you did is internal class Class2 and thus Class2 should be accessible if both are living in the same project/assembly. If you are referencing a different assembly or project wherein Class2 is contained, you have to make it public in order to access it, as internal classes can't be accessed from outside their assembly.
As for renaming: You can click Program.cs in the Solution Explorer and press F2 to rename it. It will then open up a dialog window asking you if the class Program itself and all references thereof should be renamed as well, which is usually what you want. Or you could just rename the class Program in the declaration and again open up the menu with the small blue bar (or, again, CTRL+.) and do the same, but it won't automatically rename the actual file accordingly.
Edit after your question edit: I have never used this option you used, but from quick checking I think that it's really not inside the same project then. Do the following when adding new classes to a project: In the Solution Explorer, right click the project you created and select [Add] -> [Class] or [Add] -> [New Item...] and then select 'Class'. This will automatically make the new class part of the project and thus the assembly (the assembly is basically the 'end product' after building the project). For me, there is also the shortcut Alt+Shift+C working to create a new class.
namespace TestCSharp2
{
**public** class Class2
{
int i;
public void setValue(int i)
{
this.i = i;
}
public int getValue()
{
return this.i;
}
}
}
Add the 'Public' declaration before 'class Class2'.
According to your example here it seems that they both reside in the same namespace. I conclude that they are both part of the same project (if you haven't created another project with the same namespace)
and all classes by default are defined as internal to the project they are defined in, if haven't declared otherwise, therefore I guess the problem is that your file is not included in your project.
You can include it by right clicking the file in the solution explorer window => Include in project, if you cannot see the file inside the project files in the solution explorer then click the show the upper menu button of the solution explorer called show all files (just hover your mouse cursor over the button there and you'll see the names of the buttons).
Just for basic knowledge:
If the file resides in a different project\ assembly then it has to be defined,
otherwise it has to be defined at least as internal or public.
In case your class is inheriting from that class that it can be protected as well.
I was having the same problem here. Found out that the problem was with an Advanced Property of the file. There is there an option with the name 'Compilation Action' (may be not with the exact words, I am translating - my VS is in Portuguese).
My Class1.cs file was there as "Content" and I just had to change it to "Compile" to make it work, and have the classes recognized by the others files in the same project.
Just make two projects in two different files then rename the "Program.cs" of one of the two files
and copy it then paste it next to the Program.cs of the other file and that's it.
In your project there will be a file with .csproj extension.
Double click on it to open the project in the Visual Studio. Otherwise, if you make a new class, it won't link with other classes.
When u diclare your , var
you , can use private , declarasion
using System;
private Class class;

Visual studio locking DLL because of embedding views using "embedded resource"

PROJECT A contains a View , let's call it View1.ascx marked as "Embedded Resource" in the properties window
both PROJECT A and PROJECT B and C load that view1 from the PROJECTA.DLL using a custom resource provider
This way I can reuse my views across projects.
Sadly, this causes visual studio to be unable to build PROJECT B , OR C the first time around, after each change to the PROJECTA.dll
"Error 12 Could not copy "C:\GIT\PROJECTA\PROJECTA\bin\PROJECTA.dll" to "bin\PROJECTA.dll". Exceeded retry count of 10. Failed."
Is there any way to make this work? or should I somehow move all "re-used" views to a seperate assembly? The views use classes from PROJECT A so that's why I kept them inside PROJECT A
To make everything clear: Building it a second time around usually works, and the code and views are all working, it's just a really big waste of time to have to wait 10 seconds for the first build attempt to fail.
Apparantly my assemblyresourceprovider used a AssemblyResourceVirtualFile:VirtualFile oebject that was loading my dll from Assembly.LoadFile instead of using the recommended way of loading dlls in memory as described here: http://fzysqr.com/2010/04/26/asp-net-mvc2-plugin-architecture-tutorial/
I left the old line of code in comment for you guys to see where the problem was
public override System.IO.Stream Open()
{
string[] parts = path.Split('/');
string assemblyName = parts[2];
string resourceName = parts[3];
assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName);
byte[] assemblyBytes = File.ReadAllBytes(assemblyName);
System.Reflection.Assembly assembly = Assembly.Load(assemblyBytes);
/*System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(assemblyName);*/
if (assembly != null)
{
Stream resourceStream = assembly.GetManifestResourceStream(resourceName);
return resourceStream;
}
return null;
}

Adding Project reference programmatically

Basically, after read a couple links, i tried the above code:
foreach (EnvDTE.Project proj in soln.Projects)
{
if (proj.Name == "BLL")
{
VSLangProj.VSProject vsproj = (VSLangProj.VSProject)proj.Object;
vsproj.References.Add(#"C:\Teste\DAL\bin\Debug\DAL.dll");
}
}
All paths, project names, are hard-coded on purpouse, since im still testing how to achieve it.
Though it would act like if i did
Project folder -> References -> Add reference -> Pick one, manually (compile time)
but after loading the solution, BLL project didnt contain any PERMANENT reference to DAL project.
I think that you forget to save modified project , you have to invoke Save at the end

Categories

Resources