I have Project A that uses a DLL with Source Generator B. When the Source Generator runs, I need to know the file path that A was located.
My Source Generator implements ISourceGenerator. GeneratorExecutionContext doesn't seem to contain anything relevant to file path, as far as I can tell.
Is there any way to do this?
After a lot of mucking about in the properties of GeneratorExecutionContext I finally located the caller's file path somewhere. It's easiest to just put it in an Extension method.
/// <summary>Gets the file path the source generator was called from.</summary>
/// <param name="context">The context of the Generator's Execute method.</param>
/// <returns>The file path the generator was called from.</returns>
public static string GetCallingPath(this GeneratorExecutionContext context)
{
return context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.projectdir", out var result) ? result : null;
}
Related
Is it possible to have resource files in separate folders for each language as shown below? I'd like all my English files in an "en" folder and all my Spanish files in an "es" folder. I have tried using the resources with both files in the main Resources folder (no subfolders), and it works correctly. However, when I have the files in separate "en" and "es" folders like in the image, I always get the English text even if my browser is set to display Spanish.
I've included file properties for each resource file along with the code I'm using to retrieve the value
var value = Language.Resources.ResourceManager.GetString(resourceName.Trim());
The auto-generated Resources.Designer.cs file includes the following code for the ResourceManager property. Is that first parameter "ClientInterface.Resources.en.Resources" the reason why it's always giving me English?
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClientInterface.Resources.en.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
I see it like you need to write single Resource class manually and Custom Tool for Resources should be deleted.
And you need to write your own logic for receiving right ResourceManager.
This small sample without optimizations, but you can start with this.
The auto-generated Resources.Designer.cs file includes the following
code for the ResourceManager property. Is that first parameter
"ClientInterface.Resources.en.Resources" the reason why it's always
giving me English?
It's mostly because in autogenerated resource it is loading only english resource, but you need to write your logic, how to load your resource.
Example NamespaceToResources.Language.Resources
Or NamespaceToResources.Culture.Resources
In the next sample I'm loading Resource for current Culture
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
return new global::System.Resources.ResourceManager($"ClientInterface.Resources.{Thread.CurrentThread.CurrentUICulture.Name.Replace("-", "_")}.Resource", typeof(Resource).Assembly);
}
}
I need to link a file in a comment so that others can click it and the explorer opens the folder or the file opens
I need something like this:
/// <summary>
/// Does something see file://$(SolutionDir)/SomeFolder/somefile.txt"
/// </summary>
public void MyMethod()
{}
You can try the following comment to do it.
/// <summary>
/// This is a math function I found <see href="file:///test">HERE</see>
/// </summary>
public void MyMethod()
{ }
The rule is file:/// + your relative file path.
This is my tested result:
I've got .ps1 scripts in my solution which added as .txt files into resources.
I use them in code this way:
string script = Properties.Resources.TRY_GET_GUEST_SCRIPT_SESSION_RESULT;
The problem is that I have no instruments to fast view content of this resource - the autogenerated function TRY_GET_GUEST_SCRIPT_SESSION_RESULT has only a brief annotation, in addition, has an uncomfortable 'comment' format:
/// <summary>
/// Looks up a localized string similar to Param(
/// [parameter(Mandatory=$true)]
/// [guid]
/// $SessionId
...[rest of string was truncated]"
/// </summary>
Which plugins, or code-tricks I can use to fast view (by press F12 - for ex.) resource?
I'm having an issue with RazorEngine (version 3.4.1.0).
I'm using Razor.Parse method with very simple template in a service that fires up every few minutes, and it works without any issues most of the times, but every now and then it throws this exception on me:
System.IO.FileNotFoundException:
Could not find file 'C:\Users\username\AppData\Local\Temp\cw3sv4yk.dll'.
File name: 'C:\Users\username\AppData\Local\Temp\cw3sv4yk.dll'
(cw3sv4yk is a randomly generated name)
Has anyone bumped into this issue before, and if so - any hints to what the solution would be?
Thanks,
Przemek
EDIT:
I've just noticed that I'm also getting this exception occasionally:
RazorEngine.Templating.TemplateCompilationException: Unable to compile
template. Metadata file
'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
could not be opened -- 'The process cannot access the file because it
is being used by another process.'\n\nOther compilation errors may
have occurred. Check the Errors property for more information.
EDIT_2:
One more exception that's being thrown every now and then:
System.ArgumentException: Class name is required
Using an overloaded version of Razor.Parse method which caches templates solved the issue for us:
/// <summary>
/// Parses and returns the result of the specified string template.
/// </summary>
/// <typeparam name="T">The model type.</typeparam>
/// <param name="razorTemplate">The string template.</param>
/// <param name="model">The model instance.</param>
/// <param name="cacheName">The name of the template type in the cache or NULL if no caching is desired.</param>
/// <returns>The string result of the template.</returns>
public static string Parse<T>(string razorTemplate, T model, string cacheName)
I have a project called InversionOfControl. That project has a class called IOC. It looks like this:
/// <summary>
/// This class is used to expose the unity container to the application.
/// </summary>
public class IOC
{
/// <summary>
/// The actual unity container for the app.
/// </summary>
public static IUnityContainer Container { get; set; }
}
All my projects that need to resolve unity injections have a reference to this class. Lately I have started getting this error:
Value cannot be null.
Parameter name: container
on normal resolves:
ITransmitModel transmitModel = IOC.Container.Resolve<ITransmitModel>();
When I try to inspect IOC.Container, the value in the watch window is:
The type 'InversionOfControl.IOC' exists in both 'InversionOfControl.dll' and 'InversionOfControl.dll'
I have looked in my output folder and there is only one InversionOfControl.dll file. (I even cleaned my solution and double checked the folder was empty. I then rebuilt and checked again that there is only one.)
Why does it think there are two dlls called InversionOfControl.dll?
A way to check what module is loaded at run-time is "Debug->Windows->Modules" and check out where the DLL in question is loaded from. Make sure you are not loading 2 assemblies with different versions.
As a next step I would do search for all files with this name to see if there are suspicious copies ("cd /d c:\ & dir /s /b InversionOfControl.dll").