Alias resource file namespace in C# - c#

I have an ASP.net MVC 3 project with resource files setup in folders like:
/Resources/EntityName/Views/
/Resources/EntityName/Models/
This means the namespace to access the strongly typed resource values is:
Resources.EntityName.Models.ModelA.Property1
Visual studio gives a compile time error if I try to include the namespace "resources.xxx" and it won't allow the using alias syntax either.
Is there anyway to include or atleast alias the strongly typed namespace of a resource file like it was a normal namespace?

There should be no reason why you can't use one of these objects within a class:
using YourProject.Resources.EntityName.Models;

You might try something like this (not tested, just an idea)
public class myModelA : Resources.EntityName.Models.ModelA
{ /*Leave empty here, nothing to do*/ }
Then you may be able to call the shortest myModelA instead of the complete, verbose name of the resource. Watch out because you'll not be able to access private members of your original model if you inherit it like thi.

Related

Two identical object names; how to make VS ignore one of them?

I have basic User model class that I am using but the problem is that in ASP.NET MVC there is already some property named User that is getting HTTP authentication information.
Can I somehow make Visual Studio 2012 ignore the other one and use mine? It would be pretty unpractical to write Website.Models.Users.User every time I want to access it.
Here is a picture for you to understand my problem better.
You can alias your Namespace or Class, or Microsoft's Namespace or Class:
Replace:
using Website.Models.Users;
With:
using myUsers = Website.Models.Users;
or
using myUser = Website.Models.Users.User;
Then use it as: if(myUser. or if(myUsers.User. in your code
Alternatively, you could just rename your classes so there are no collisions.
While Tom Studee had a good idea, there's an even better one.
Not only can you alias namespaces, you can alias classes!
Use this;
using HTTPUser = Website.Models.Users.User;
and then when you want to access that use use HTTPUser for that type of user and just User for the normal one.

How to avoid namespace and source file name confliction in C#?

I have a class let's say it's called "Apples". Let's say that class is in a .cs file in a folder called "Apples"
Project
-Apples
-Apples.cs
-main.cs
How can i reference it without writing this:
Main.cs
Apples.Apples.testVar = 2;
and just write
Main.cs:
Apples.testVar = 2;
Is there a way to do this, or will i have to put up with it or change the folder name?
put this at the top of your file -
using Apples = Apples.Apples;
If you have a folder in visual studio and create a class in it, Visual Studio (and possibly other IDEs) will automatically append the folder's name to the namespace of any file created from that folder.
That DOES NOT mean in any way that the namespace has to stay that way. The "folder" is purely for organizational purposes and plays no part in the compilation of your code. The filename doesn't matter to the actual code either. If you look in your Apples.cs just change:
namespace Apples.Apples
{
//....
to
namespace Apples
{
//...
It's simply the rule that your IDE is using as an assumption to what you want. You're not required to follow it.
EDIT: At least that's what I assume to be the misunderstanding here as you're focusing on the folder name - which means nothing to the code and only matters to you. Additionally as previously mentioned you might be hung up on ambiguity between namespace name and class name. As mentioned in other answers it's a bad idea to name a class the same as it's namespace.
By default the global namespace for your project will be the same name as your project. So if you named your project "Apples" and then made a folder called "Apples" and created a class within that folder called "Apples" - You'd then navigate to your class by following the chain of namespaces:
Apples.Apples.Apples
You're drawing the conclusion that you have to do this based on the folder/file names but it's really the namespaces/classes. You have several options here but the bottom line is in order to remove confusion and mess 2 or all 3 of those "Apples" need to change. Changing the file name or folder name will not work. you have to change the class name and at least one of the namespace names. Something more appropriate:
AppleProject.Apples.AppleBase
or even as simple as:
Apples.Apple // removed the extra namespace in the middle
You could alias "Apples" in your using statements:
using Apples = Apples.Apples.testVar;
Or whatever you'd like to make it easier to read.
Yes if you are using C# you just add it in the using references up top of your code file you are on:
EG:
using Apples.Apples;
You just need to ensure you have the reference to the project set if it is not in your current project.

How can I avoid using magic strings when using ResourceManager.GetString()?

I have a resource file in a Class Library project. I'm using this resource file to hold various messages the user may end up seeing.
For example, the name of the resource is "InvalidEmailAddress" and the value in the en-US resource file is "Invalid Email Address".
When I call the ResourceManager's GetString(string) method I am doing this:
return resourceManager.GetString("InvalidEmailAddress");
However, this seems really bad to me. What if somebody changes the name of the resource? Now my statement will return a null value.
Is there a way around this issue?
UPDATE: Localization is an important factor here. The resource manager is used in order to ensure I can change the culture and get appropriate string values.
You can instead use an automatically generated class - the magic string constants will be removed from the code and replaced with strongly typed access methods. VS names this file ResourceName.Designer.cs and updates it every time resx is modified in VS.
Sample of a generated method:
internal static string String1 {
get {
return ResourceManager.GetString("String1", resourceCulture);
}
Note: while creating this file is the default behavior when you add a new resource in VS, you may have disabled it or you may have tried to use the generated resource outside the assembly. In that case, make sure to set the "Custom Tool" property or resx file to "PublicResXFileCodeGenerator" or "ResXFileCodeGenerator" (later if you use resources only inside a single assembly). (Thanks #dbaseman for comment).
When you create a Resource, it will be generated strongly typed in the Resources namespace.
You can access it by Resources.ClassName.InvalidEmailAddress where ClassName is the name of your Resource (resx) file.

How to determine the code-file filename from a compiled application at runtime

Let's say I have an application with two files.
Console.cs and Business.cs
Console.cs has program Main class.
Business.cs has three classes named Customer, Order and Orderline.
Is there anyway in C# to determine at runtime (maybe with reflection) that the business objects are in a file named Business.cs?
The C# compiler does not emit this information into the DLL, so it's not available through reflection. However, as you'll be aware from debugging, the debugger can match up compiled locations to source code locations. It does this through PDB files. So it might be theoertically possible for you to ship your PDB files, and invoke the unmanaged debugger or diagnostic symbol store API (see General Reference > Unmanaged API Reference in MSDN) to determine where a given method was defined. You can't really do this for a class, though, because a class could be spread across multiple files using partial classes.
If you compile in debug mode you can probably use Cecil (part of Mono project) to extract the source filenames from the debug symbols. But when you compile in release mode this information probably gets lost.
However, if you need to do this, for other purposes than for example static analysis of your software, you are probably on the wrong track and should think of another solution.
If you put the classes in a Business namespace you could use reflection to find if an object comes from that namespace:
namespace Business {
class Customer {}
class Order {}
class OrderLine {}
}
var myObject = new Customer();
Console.WriteLine(myObject.GetType().Namespace); // writes "Business"
I believe the closest you'll get is typeof(Customer).Assembly.Location. However, this will only give you the DLL, not the location of the source code (which makes sense, since the source code would normally not be included with the binaries).
*.PDB (debug info files) files should have that information. Otherwise I see no way to get it, since code files is just an abstraction which compiled code should not care about.
not sure what your use case is, however if some one is calling you then you can add
compiler directives
[CallerFilePath] string file = "", [CallerLineNumber] int LineNo = 0
in your method.
if not than your best way of accessing this is by using the .pdb file that get's generated. The format is published and a C++ dll is available that can be used to access the file however the easiest way to read the file (and possible line number) if included in the pdb file is using stacktrace
You can access the stack in an exception, so if a class allows you to throw an exception by passing null where you should not than try catch it and you have your stack trace.
if you need the calling file but do not want to add the compiler directives as some one can simply overwrite it you can do something like:
StackTrace st = new StackTrace(new StackFrame(1));
st.GetFrame(1).GetFileName());
Assuming :
You have a project (probably technical with some extension methods etc) that all other projects in your solution reference (let's name it "NameSpaceGloballyVisibleByAllProjects")
You are using SDK-style csproj for your project (otherwise you'll have a little more work)
People in your team code without doing fancy things (ie: "class" / "struct"/ "enum" keywords are at the beginning of their own line in your .cs files).
It means that, by adding this class in "NameSpaceGloballyVisibleByAllProjects":
using System;
using System.Runtime.CompilerServices;
namespace NameSpaceGloballyVisibleByAllProjects
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true, Inherited = false)]
public class MemorizeFilePathAttribute : Attribute
{
public string Path() { return _filepath; }
public MemorizeFilePathAttribute([CallerFilePath] string filepath = "")
{
_filepath = filepath;
}
readonly string _filepath;
}
}
You can simply use it like this:
using System.Reflection;
using NameSpaceGloballyVisibleByAllProjects;
Type type = typeof(Program);
var files = type.GetCustomAttributes<MemorizeFilePathAttribute>(false).Select(att => att.Path).ToList();
Note: As you notice there are more than one file! This is because of "partial" keyword in C#. So it's up to you to use "files.Single()" or not...
We just need to add this attribute above all types now
We can do that in Visual Studio with Ctr-H (Find-and-Replace).
Select All Solution
Check options "regex" & "case sensitive"
Find: "^( *)([a-z][a-z ]*)? (class|struct|enum) "
(without double quotes, but with the final ' '!)
Replace by: "$1 [NameSpaceGloballyVisibleByAllProjects.MemorizeFilePath]\r\n$1$2 $3 "
(without double quotes, but with the final ' '!)
Be ready for this to take a little time (Go get a coffe... or tea)

Can you use the same Enum in multiple entities in Linq-to-SQL?

In my persistence layer, I've declared a load of Enums to represent tables containing reference data (i.e. data never changes).
In Linq2SQL, I am able to set the type of an entity property to an enum type and all is well, but as soon as I set a second entity's property to use the same enum type, the Code Generator (MSLinqToSQLGenerator) start generating an empty code file.
I assume that MSLinqToSQLGenerator is quietly crashing. The question is why, and are there any work-arounds? Anyone else experienced this problem?
Is your enum by any chance in a file named the same as the dbml? There is a bug in 3.5 (fixed in 4.0) where conflicts cause an empty file. Oddly, usually moving the using directives (and right-click; run custom tool) fixes it.
So if you have "foo.dbml" and your own "foo.cs" (in the same folder) with:
using System;
namespace MyNamespace {
}
it will break (generate an empty foo.designer.cs). If you have:
namespace MyNamespace {
using System;
}
it will work. I'm not kidding. Likewise, renaming "foo.cs" to "bar.cs" (and right-click, run custom tool) will fix it.
Oddly, I've discovered that this behavior only occured with an Enum named "GrantType". As soon as changed the name of the enum, the generator started working again.

Categories

Resources