I created my first source generator (ISourceGenerator) with public property and public method.
Let this class be like this:
public partial class MyClass1 // Manually written code
{
}
public partial class MyClass1 //Source Generated code
{
public string GeneratedProperty { get; set; }
public string GeneratedMethod() => "lala";
}
Both of these classes are located in the same namespace (for example, MyNamespace - it doesn't matter really).
So, I'm trying this:
var myClass = new MyClass1(); // Correct
Console.WriteLine(myClass.GeneratedMethod()); //Wrong, "MyClass1 doesn't contain definition for GeneratedMethod..."
When I say MSVS generate sources as files in the concrete directory, I have the code above working well.
So, I want to have an ability to use generated code "on fly" when I write code without generation source files each time manually. Also earlier manually generated source files are not deleted when I'm generating new source files.
Is it possible?
Thank you.
UPD. I have this message from Visual Studio:
"Warning CS8032 An instance of analyzer Generators.Factory.AbstractFactoryGenerator cannot be created from ...\bin\Debug\netstandard2.0\SourceGeneratorsLibrary.dll: Exception has been thrown by the target of an invocation."
Maybe this significant?
UPD2. https://pastebin.com/qtvrugu3 - this is my Source Generator code. Pls, don't blame me, It's just my first steps.
As far as I know, programming is case sensitive, well at least C# so myClass() is different from MyClass(). also hence you are using the string data type, try casting it as string via
Convert.ToString(MyClass1().GeneratedMethod());
or
MyClass1().GeneratedMethod().ToString();
hope this answers you question.
It seems you have developed your analyzer but not actually referenced it from a project?
To use your analyzer you simply add it as as project reference, but make sure it's marked up as an analyzer in the .csproj file:
<ItemGroup>
<ProjectReference Include="MyGenerator\MyGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
Or something like that, adjusted to your solution.
Related
Suppose I have two files in my current working directory:
// file1.cs
Console.WriteLine("file1");
//file 2.cs
Console.WriteLine("file2");
In powershell, I do a dotnet new and delete the automatically generated Program.cs file. Then I do a dotnet build and get an error:
Only one compilation unit can have top level statements
I understand why this occurs, but I would like to be able to have full control of which .cs file is being targetted, while the other ones get ignored.
Is there any way to achieve this without having to create a whole new project for every file?
Doing this with .NET doesn't seem to be possible as of now. An issue on the dotnet/sdk GitHub has requested for this feature to be implemented.
However, you can use the C Sharp Compiler to compile a Windows executable and specify a .cs file with csc file1.cs
file1.cs:
using System;
Console.WriteLine("File 1");
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements
These files both use top-level statements. It implies that they both contain the Main method where program execution starts. You can only have one entry point. Generally, C# code is going to be contained within classes. Define a class in one (or both) files and put your methods within.
// Program.cs
public class Program
{
static void Main()
{
Console.WriteLine("Program.cs");
}
}
// Util.cs
public class Util
{
public static void Display()
{
Console.WriteLine("Util.cs");
}
}
I'm fairly new to .NET and I'm trying to get an old program to work that no longer has it's .csproj file. I've managed to receive an old .sln file from the creator and opened the solution in VS.
From what I can see this is a Developer Web Server project?
Here is the issue.
In the folder Smreka there are 2 files, log.cs and smreka.cs. The log.cs contains the implementation of a class Logger, which I am trying to import in to smreka.cs. They are both using the same namespace Bum.Iglavci.Smreka so as far as I know, I should be able to import the Logger class without any issues.
The problem is that the compiler just can't see it. If I try to directly import it with using static Bum.Iglavci.Smreka.Logger;, I get an error Feature 'using static' is not available in C# 5. Please use language version 6 or greater.
I would like to know why the namespace can't see each other. Is it because I'm missing the .csproj file? Does Developer Web Server even need a .csproj file? If so what's the best way to generate one?
EDIT:
Due to some confusion I'll try to add more details regarding how log.cs and smreka.cs look like. The files are actually a lot longer but I think this should give an idea.
log.cs:
namespace Bum.Iglavci.Smreka{
public class Logger{
public Logger(){
}
public void DoSomething(){}
}
}
smreka.cs:
namespace Bum.Iglavci.Smreka{
public class Baza{
private Logger log;
public Baza(){
log = new Logger();
}
}
}
The compiler has no idea what Logger is under property private Logger log; It states the error The type or namespace name 'Logger' could not be found (are you missing a using directive or an assembly reference?)
I think the namespace is correctly placed, that's why i have a feeling there's something wrong with the project or the solution itself that i need to fix.
Since both classes are in the same namespace they are already able to use each other. You can acces the class by simply doing the following. Let's take Log as the class to call the other class.
Log class:
namespace Bum.Iglavci
{
public class Log
{
public static void ExecuteDoSomething()
{
Smreka.DoSomething();
}
}
}
Smerka class:
namespace Bum.Iglavci
{
public class Smerka
{
public static void DoSomething()
{
//execute code here
}
}
}
It could be possible that the files have the Buil Action property set to
None this will not compile the files. Set it to C# Compiler, this should solve it.
If you don't know how to acces the properties of a file.
Right click the file
Navigate to Properties in the bottom of the list
Set the Build Action to C# compiler (see image)
I found no simple solution. I now created a new .net framework application project and added the files in to the new project. For some reason the namespace works correctly now and the files can see each other in the same namespace.
Yes the error comes from the fact that you don't have a .csproj file.
Such files contain the list of files to compile when building a project. Just having the solution file is not enough.
I suggest some readings on project and solution using Visual Studio :
https://learn.microsoft.com/en-us/visualstudio/ide/solutions-and-projects-in-visual-studio?view=vs-2022
https://learn.microsoft.com/en-us/visualstudio/get-started/tutorial-projects-solutions?view=vs-2022
Here is my code:
using ProtoBuf;
[ProtoContract]
[ProtoInclude(500, typeof(SampleClassDrv))]
public class SampleClass
{
[ProtoMember(1)] public int theInt;
[ProtoMember(2)] public string[] items;
public SampleClass(){}
public SampleClass(int c) {this.theInt = c;}
}
[ProtoContract]
public class SampleClassDrv : SampleClass
{
[ProtoMember(1)] public int theOtherInt;
public SampleClassDrv(){}
public SampleClassDrv(int b):base(1){this.theOtherInt=b;}
}
To compile my DLL I run the following code:
RuntimeTypeModel rModel = TypeModel.Create();
rModel.AllowParseableTypes = true;
rModel.AutoAddMissingTypes = true;
rModel.Add(typeof(SampleClass), true);
rModel.Add(typeof(SampleClassDrv), true);
rModel.Compile("MySerializer", "MySerializer.dll");
Finally I should be able to initialize by RuntimeTypeModel from the dll like so:
MySerializer serializer = new MySerializer();
serializer.Serialize(stream, object);
But Unity throws the following exception
Internal compiler error. See the console log for more information.
[...]
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
Interestingly enough if I go back and remove the line
[ProtoMember(2)] public string[] items;
It works as expected...
It is also worth noting the RunTimeModel works as expected if used after adding the classes instead of attempting to use dll.
My environment:
Unity3D 4.3.4
Protobuf-net r668
using protbuf-net.dll in Full/unity
I would greatly appreciate if someone could point out the error in my ways.
EDIT
From the suggestion by Flamy I changed form string[] to List
[ProtoMember(2)] public List<string> items;
Sadly the error still persists.
Another Note
Also I decided to use a dll decompiler to see what is going on. I was not able to decompile the dll until the "string[] items" variable was removed.
SOLVED
I think it is related to some issue with compiling the DLL with Unity3D.
When I created the project in Visual Studios with the code I showed above everything seems to be working as expected. Which is a relief as this seems like it would be a huge issue if protobuf could not serialize string[].
I followed the article provided by BCCode to setup the visual studio project and compile the DLLs.
Now all I need to do is create the dll with my large scale project! Fingers Crossed
Thanks everyone for their help!
Are your references correct?
%project dir%\Library\ScriptAssemblies\Assembly-CSharp.dll
Also take a look here:
http://purdyjotut.blogspot.com/2013/10/using-protobuf-in-unity3d.html?m=1
Serilizing array of strings using Binary serilization or a serilization method that uses binary format (protobuff in this case) will always result in so many issues. The reason is String by itself is an array of chars,which doesnt have a defined size, meaning it dont know where one string ends and the next starts... Usually we serialize string array one by one instead of the whole array. so I advice you to to use a property which does that (hopefully protobuff accepts attributes on properties!) or create a list of strings instead (though i haven't tested yet it should work!)
I'm trying to allow a user to enter data into a textbox that will be added to the web.config file. I've added the relevent lines to the web.config file but when I make this class all goes wrong.
I keep getting the are you missing a using directive or assembly refenrence error whenever I try to run my app. I have looked at the other times this question has been asked and can't seem to figure out where I'm going wrong. The thing is that I am extremely new to Visual Studio and am just left blank at what could be the answer.
Below here is the class file that's generating the error. I hope I've included everything you need to assist me. Thank you.
using System.Collections.Generic;
using System.Linq;
using System.Configuration;
namespace WebConfigDemo
{
public class CompanyConfigSection : ConfigurationSection
{
[ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
public CompanyConfigCollection Companies
{
get
{
return (CompanyConfigCollection)this[""];
}
set
{
this[""] = value;
}
}
}
public class CompanyConfigElement : ConfigurationElement
{
[ConfigurationProperty("id", IsKey = true, IsRequired = true)]
public int Id
{
get
{
return (int)this["id"];
}
set
{
this["id"] = value;
}
}
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get
{
return this["name"].ToString();
}
set
{
this["name"] = value;
}
}
} '
public class CompanyConfigCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new CompanyConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((CompanyConfigElement)element).Id;
}
}
public class CompaniesConfig
{
private static readonly Dictionary<int, CompanyConfigElement>
Elements;
static CompaniesConfig()
{
Elements = new Dictionary<int, CompanyConfigElement>();
var section = (CompanyConfigSection)ConfigurationManager.GetSection ("companies");
foreach (CompanyConfigElement system in section.Companies)
Elements.Add(system.Id, system);
}
public static CompanyConfigElement GetCompany(int companyId)
{
return Elements[companyId];
}
public static List<CompanyConfigElement> Companies
{
get
{
return Elements.Values.ToList();
}
}
}
} '
Any help is appreciated
You probably don't have the System.Configuration dll added to the project references. It is not there by default, and you have to add it manually.
Right-click on the References and search for System.Configuration in the .net assemblies.
Check to see if it is in your references...
Right-click and select Add Reference...
Find System.Configuration in the list of .Net Assemblies, select it, and click Ok...
The assembly should now appear in your references...
.Net framework of the referencing dll should be same as the .Net framework version of the Project in which dll is referred
If you've tried the above solutions and haven't found the answer, make sure that the .NET versions of all projects are the same.
I ran into this problem when importing a .NET version 4.6.1 into a .NET version 4.6.2 project. Without any warnings from Visual Basic!
More Info: The type or namespace name could not be found
Your using statements appear to be correct.
Are you, perhaps, missing the assembly reference to System.configuration.dll?
Right click the "References" folder in your project and click on "Add Reference..."
This problem would be caused by your application missing a reference to an external dll that you are trying to use code from. Usually Visual Studio should give you an idea about which objects that it doesn't know what to do with so that should be a step in the right direction.
You need to look in the solution explorer and right click on project references and then go to add -> and look up the one you need. It's most likely the System.Configuration assembly as most people have pointed out here while should be under the Framework option in the references window. That should resolve your issue.
I have observed a quote ' in your 1st line and also at the end of your last line.
'using System.Collections.Generic;
Is this present in your original code or some formatting mistake?
I had the same problem earlier today. I could not figure out why the class file I was trying to reference was not being seen by the compiler. I had recently changed the namespace of the class file in question to a different but already existing namespace. (I also had using references to the class's new and previous namespaces where I was trying to instantiate it)
Where the compiler was telling me I was missing a reference when trying to instantiate the class, I right clicked and hit "generate class stub". Once Visual Studio generated a class stub for me, I coped and pasted the code from the old class file into this stub, saved the stub and when I tried to compile again it worked! No issues.
Might be a solution specific to my build, but its worth a try.
In some cases, when necessary using has been obviously added and studio can't see this namespace, studio restart can save the day.
I was getting warnings about different versions in .NET framework; I ignored them.
The project compiles fine making the change in the solution's properties.
I'm using Visual Studio Code and could not use instructions from above so I found another way to fix the problem with referencing to namespace from another file.
All what need to be done is to add include to your .csproj file e.g:
<ItemGroup>
<Compile Include="filename.cs" />
</ItemGroup>
Then you can use namespaces from filename.cs
The following technique worked for me:
1) Right click on the project Solution -> Click on Clean solution
2) Right click on the project Solution -> Click on Rebuild solution
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