I have got a partial class in my C# project i.e. auto-generated code from Entity Framework. Now I want to modify or add some more functionalities, properties or methods to that class. I have the auto-generated class code under EntityFrameworkModel.tt\Author.cs tab in the project while the other related classes are in another folder i.e. GraphData in the same project.
I also know that the name of partial classes should be same while file name may be different or same as well. I did same but when I defined the object for Author.cs as:
protected override EvoObject ConvertCPV(Author _author)
{
if (_author.???)
{
//...
}
}
I can't access the methods defined in GraphData\Author.cs (The question marks in example code) whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only accessible.
Here I attached the Solution Explorer image as:
How can I access the properties and methods from both classes?
I have a similar set up in a project also.
To keep things tidy I also have folders where I place certain partial classes, you just need to ensure the namespace is the same as the auto generated class.
When you add a new class to a folder the namespace will automatically contain the name of the folder - you can just remove the folder name from the namespace - you should just have the Project name in this scenario.
If the namespaces are different then the partial classes are not part of the same class. This is why you can't access the new functions/Properties.
Also, even though your file name and class names can be different, it is better to keep them the same - it will be easier to find a class if the file has the same name.
Check out https://msdn.microsoft.com/en-us/library/wa80x488.aspx
It says "The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace." It does not explicitly state this, but that implies that the partial definitions of the class must be declared in the same namespace. It doesn't matter which files in the project contain the classes, or what folders they are in.
using System;
namespace DemoConsoleApp
{
class Program
{
static void Main(string[] args)
{
SameNamespace.PartialClass.MethodOne();
SameNamespace.PartialClass.MethodTwo();
DifferentNamespace.PartialClass.MethodThree();
}
}
}
namespace SameNamespace
{
public partial class PartialClass
{
public static void MethodOne()
{
Console.WriteLine("Method One.");
}
}
public partial class PartialClass
{
public static void MethodTwo()
{
Console.WriteLine("Method Two.");
}
}
}
namespace DifferentNamespace
{
public partial class PartialClass
{
public static void MethodThree()
{
Console.WriteLine("Method Three.");
}
}
}
Make your own class outside of EntityFrameworkModel.tt - name it Author.cs, make the class partial.
The whole idea of partial is to allow code generators not to care about your code. Of you modify a generated class, the next regeneration kills the changes.
I did same but when I defined the object for Author.cs as:
Ah, no, you did not because then you claim your definition is:
protected override EvoObject ConvertCPV(Author _author)
Which is NOT defining the object.
I can't access the methods defined in GraphData\Author.cs
Because namespace? Check the namespaces - bad to have them in a subfolder when they belong in a the same namespace as EntityFrameworkModel.tt
whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only
accessible.
Partial classes do not allow changes in another partial - not for the moment, a substition syntax is considered.
Related
I have a namespace that will change somewhat frequently in my project (each product generation) and would like to keep references to that specific namespace contained to the file where I define a base class. In other files I define child classes that usually can get by with getting references to the namespace by inheritance, but I am having trouble with one case as the objects are very specific and I would prefer to link to the namespace within the base class rather than each object.
BaseClass.cs
namespace CommonNameSpace
{
using _productSpecificNameSpace;
_productSpecificNameSpace.thing.otherthing thingotherthingGood = _productSpecificNameSpace.thing.otherthing.Success;
_productSpecificNameSpace.thing.otherthing thingotherthingBad = _productSpecificNameSpace.thing.otherthing.SpecificFailure;
public class BaseClass
{
}
}
SubClass.cs
namespace CommonNameSpace
{
public class SubClass : BaseClass
{
var yeaOrNeigh = thingotherthingGood
}
}
How can I access _productSpecificNameSpace in SubClass.cs without having to call it _productSpecificNameSpace in each subclass, or name every possible object that I will need in BaseClass? Is there a way to get an alias to a namespace attached to a class for inheriting?
Edit: Ideally, I would like to have access to the data types in the interchangeable namespace, as it is mostly a library of enums. Wouldn't having an interface replace the type of these enums with an interface type that would be incomparable with calls to APIs expecting the underlying type?
If you use an interface, you can then instantiate the generation you want to at runtime, without affecting any existing code:
interface IMyThing
{
void DoStuff()
}
abstract class BaseThing : IMyThing
{
public virtual void DoStuff()
}
Generation1:
class MyGen1 : BaseThing
{
public override void DoStuff()
{
// I'm Gen 1
}
}
Generation2:
class MyGen2 : BaseThing
{
public override void DoStuff()
{
// I'm Gen 2
}
}
I have Created one ConsoleApplication to understand Access Specifiers.
Below is my code for internal, I can access this class from outside the Assembly.
namespace Assembly_1 //This is first assembly.
{
public class Base
{
//internal class
internal class B
{
public static void fnB()
{
Console.WriteLine("fnB");
}
}
}
}
namespace Assembly_2 //This is second assembly.
{
public class Derived : Assembly_1.Base
{
public class D
{
public void fnD()
{
B.fnB();//how can I access this class?
}
}
}
}
And this is where I am Accessing it.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly_2.Derived.D d = new Assembly_2.Derived.D();
d.fnD();
}
}
}
My Question
Right now I can Access Class B and it's methods like fnB() in Derived.
Everything works fine. but How?
How can I access the B Class outside Assembly_1?
As I worte in the comments:
You are confusing the namespace and assembly terms.
You can read about it here:(Assemblies and Namespace)
Many namespaces can be defined in a single assembly.
If you would like to check and understand the internal modifier,
then you would have to create a new class library project (that will compile into a different assembly), define the Base class there
and add a reference to it in your main console application.
Then you will see that you don't have access to it anymore and the code will not compile.
How can I access the B Class outside Assembly_1?
Because you're confusing namespaces and assemblies. An assembly is a collection of one or more namespaces, contained within a .dll or .exe file.
See also: MSDN: Assemblies in the Common Language Runtime and Understanding and Using Assemblies and Namespaces in .NET.
What you call Assembly_1 and Assembly_2 are namespaces within the same assembly.
Because internal members are visible within the same assembly, you can use Assembly_1.B from Assembly_2.D, because both namespaces reside in the same assembly.
I imported a table from the database using designer, then I've edited the corresponding cs file to add extra functionality to the model (it's a partial exactly for this reason). Now I came up with some ideas on how to make that functionality more reusable and packed that into a base class (so in the context code I have partial class Foo : BaseClass). I made the partial class inherit the base class and all is fine... except for partial methods.
The generated partial class has some partial methods that normally don't have any code (namely the OnCreated method). I've added an OnCreated method to the base class and put a breakpoint in it, but it's never hit.
Can I somehow make a partial class take the code for partial method from a non-partial parent or am I doing something wrong here?
Background: I have a certain structure (columns containing author's id, id of user who was the last one to modify the record and dates of create and update dates) that is appearing in multiple tables and I'm trying to define most code for handling that in a single place in my project. It involves having uniform access to associated users and I had some luck doing that by defining associations in my base class (basically this, but with few modifications). So far it appears to works perfectly, except for the fact that I should be assigning default values to storage variables inside of the constructor of the generated class
(this._SomeVariable = default(EntityRef<SomeModel>)). However modifying the generated code is pointless, since all changes will be lost when the file is generated anew. So the next best thing would be to implement OnCreated partial method which is run at the end of the generated class. I can implement that in the non-generated cs file for my model, but I'd rather put it inside the base class which is shared with all similar models.
Here is some minimal code to make it more clear:
Generated code:
partial class Foo
{
public Foo()
{
// does some initialization here
this.OnCreated();
}
partial void OnCreated();
}
Extended code for Foo:
partial class Foo : BaseClass // Thanks to this I can use the uniform JustSomeModel association
{
// This code here would run if it was uncommented
// partial void OnCreated() {}
// However I'd rather just have the code from base.OnCreated()
// run without explicitly calling it
}
Base class:
public class BaseClass
{
protected EntityRef<SomeModel> _SomeVariable;
[Association(Name = "FK_SomeModel", Storage = "_SomeVariable", ThisKey = "SomeModelId", OtherKey = "Id", IsForeignKey = true)]
public SomeMode JustSomeModel
{
get
{
return this._SomeVariable.Entity;
}
}
// This never runs
public void OnCreated()
{
this._SomeVariable = default(EntityRef<SomeModel>)
}
}
The best solution I can think of right now would be to do this:
partial class Foo : BaseClass
{
partial void OnCreated()
{
base.OnCreated(); // Haven't really tested this yet
}
}
However this means I will have to add this piece of code to every model inheriting from BaseClass that I use and I'd rather avoid it.
Based on information posted by Eugene Podskal I can assume this cannot be done and my best bet is implementing the partial method and calling base method inside it.
partial class Foo : BaseClass
{
partial void OnCreated()
{
base.OnCreated();
}
}
Edit: Tested it and it works.
I have partial class User generated by LINQtoSQL as shortly following:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.[User]")]
public partial class User : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
...
Then I created separate folder "Proxy" in my project and put there extra piece of User class:
namespace LINQtoSQL_sample.Proxy
{
public partial class User
{
public static string GetActivationUrl()
{
return Guid.NewGuid().ToString("N");
...
Issue happens when I try to invoke that extra static method from another part of same project. Let's say I have once more folder "SqlRepositoryImpl" and another one partial class there:
namespace LINQtoSQL_sample.SqlRepositoryImpl
{
public partial class SqlRepository
{
public bool CreateUser(User instance)
{
if (instance.ID == 0)
{
instance.added_date = DateTime.Now;
instance.activated_link = LINQtoSQL_sample.Proxy.User.GetActivationUrl();
...
As you can see I explicitly defined which part of User class I'm calling for because IntelliSense didn't suggest me my extra method.
Please, advise why such happens and where I'm wrong?
As you can see I explicitly defined which part of User class I'm calling for because IntelliSense didn't suggest me my extra method.
When you call a method from a class, there are no “parts” of the class anymore.
If you need to (and can) specify the full namespace of the class to invoke a method from it that means you actually have two different classes in two different namespaces. If the two partial declarations are in different namespaces, then you have actually declared two separate classes, not a single class from two parts.
In C#, can you make a class visible only within its own namespace without living in a different assembly? This seems useful for typical helper classes that shouldn't be used elsewhere.
(i.e. what Java calls package-private classes)
You can make the classes internal but this only prevents anyone outside of the assembly from using the class. But you still have to make a separate assembly for each namespace that you want to do this with. I'm assuming that is why you wouldn't want to do it.
Getting the C# Compiler to Enforce Namespace Visibility
There is an article here (Namespace visibility in C#) that shows a method of using partial classes as a form of "fake namespace" that you might find helpful.
The author points out that this doesn't work perfectly and he discusses the shortcomings. The main problem is that C# designers designed C# not to work this way. This deviates heavily from expected coding practices in C#/.NET, which is one of the .NET Frameworks greatest advantages.
It's a neat trick… now don't do it.
I don't think that what you want is possible.
internal is assembly (strictly speaking module) privacy. It has no effect on namespace visibility.
The only way to achieve privacy of a class from other classes within the same assembly is for a class to be an inner class.
At this point if the class is private it is invisible to anything not in that class or the outer class itself.
If protected it is visible to everyone that could see it when private but is also visible to sub classes of the outer class.
public class Outer
{
private class Hidden { public Hidden() {} }
protected class Shady { public Shady() {} }
public class Promiscuous { public Promiscuous() {} }
}
public class Sub : Outer
{
public Sub():base()
{
var h = new Hidden(); // illegal, will not compile
var s = new Shady(); // legal
var p = new Promiscuous(); // legal
}
}
public class Outsider
{
public Outsider()
{
var h = new Outer.Hidden(); // illegal, will not compile
var s = new Outer.Shady() // illegal, will not compile
var p = new Outer.Promiscuous(); // legal
}
}
In essence the only way to achieve what you desire is to use the outer class as a form of namespace and restrict within that class.
No, it is possible. You can use internal class in another assembly.
For example I have a internal string extension class that located in SharMillSoft.Core assembly, if I want use it in another assembly that name is SharpMilSoft.Extension, I must use assembly attribute like as below:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SharpMilSoft.Extensions")]
namespace SharpMilSoft.Core.Extensions.Strings.Public
{
internal static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return string.IsNullOrEmpty(data);
}
}
}
And I use this class in SharpMilSoft.Extension assembly like as below:
namespace SharpMilSoft.Extensions.Strings
{
public static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return Core.Extensions.Strings.Public.SharpStringExtensions.IsNullOrEmpty(data);
}
}
}
Note: Then SharpMilSoft.Extensions assembly will be friend assembly for SharpMilSoft.Core assembly
For more details about friend assembly, you can visit this link : Friend assemblies
If you have a single assembly you can define as many namespaces in that assembly as you want but no matter what modifier you apply in the IDE you will always be able to see the classes in other namespaces.
Not sure if it is directly possible, but a few good ways to fake it would be:
1) Have the classes that need this sort of stuff inherit from a single class which has the helper class as an internal class.
2) Use extension methods and then only reference the extension methods within the namespace.