I have a strange problem in my project. I have a class that inherits from a base class (which again inherits from another base class) and overrides a function. However, when that function is called it never calls the overridden function, but the base function.
However, when I override that function in the middle class it is called. But this is confusing: let's explain with a drawing :)
lib GuiShared
class bScreen
virtual function InitializeRoc
lib TigerControlRoot
class bTigerScreen
override function InitializeRoc <-- when overriden here it gets called
lib TigerControlRootCommonScreens
class CheckInRules
override function InitializeRoc <-- not called :s
The constructor gets called however...
Here's my (simplified) code:
The shared base class
namespace Ppb.GuiShared.Screens {
public partial class bScreen<T> : Ppb.Controls.pPanel where T : FrameworkMiddleware.Framework.Remoting.Remotable, FrameworkMiddleware.IInitialize, new() {
public virtual void Load(bMain<T>.LoadEventArgs args) {
log.Trace("InitializeRoc " + this.GetType().FullName);
InitializeRoc(args);
_hasLoaded = true;
}
protected virtual void InitializeRoc(bMain<T>.LoadEventArgs args) { }
}
}
project base class
namespace Tiger.ControlRoot.Screens {
public partial class bTigerScreen : Ppb.GuiShared.Screens.bScreen<roc.Tiger> {
public bTigerScreen(GuiSettings settings, roc.Tiger tiger)
: base(settings, tiger) {
InitializeComponent();
InitializeMenu();
}
}
}
The failing class (or any other class from that lib)
namespace Tiger.ControlRoot.CommonScreens {
[ControlRoot.Screens.TigerScreenInfo("Testje", Tiger.ControlRoot.Screens.TigerScreenInfoAttribute.elevel.User, true)]
public class CheckInRules : ControlRoot.Screens.bTigerScreen {
public CheckInRules(GuiSettings settings, roc.Tiger tiger)
: base(settings, tiger) {
}
protected override void InitializeRoc(Ppb.GuiShared.bMain<TigerMiddleware.TigerRoc.Tiger>.LoadEventArgs args) {
base.InitializeRoc(args);
}
}
}
And if that wasn't enough, when I try to call some function on the base class I receive a TypeLoadException.
GenericArguments[0], 'TigerMiddleware.TigerRoc.Tiger', on 'Ppb.GuiShared.bMain`1+LoadEventArgs[T]' violates the constraint of type parameter 'T'.
Similar code with the same GuiShared lib is used in another project and there there are no issues.
Okay, thanks for all (the) response(s), but I fixed it in the meantime.
The problem was the following:
The failing class is in an dll from which its output path in debug mode is set to the executable's plugin folder. No problem so far, but it also copies its dependencies into that folder.
However, some of the dependencies are already copied to the executable's root folder. The executable when it startups searches all the plugins in the plugin folder and when required instantiates the plugin.
The problem then is that the plugin uses the dependencies from in the plugins folder while the executable uses the dependencies from the root folder which are basically the same file in a different dir, so while running the clr sees them as 2 different dll's and that really confuses the clr :).
So when the shared dependencies aren't copied to the plugins folder, everything runs fine because the plugins use the depedencies from the root folder and thus the same dll's.
Related
I must be overlooking something simple. I'm trying to update a class that once used to compile. I'm mostly swapping out similar classes under different namespaces for new code, cleaning up so to speak.
I have one method, TakeAction, that isn't overriding for me. Parent (abstract) class:
namespace MyNamespace.StandardNoteReceiverService
{
public abstract class NoteReceiverHandler : BaseIntegrationService
{
private Vendor.Sys.Services.ReceiveNoteData _ReceiveNoteData;
public NoteReceiverHandler() {}
public NoteReceiverHandler(Vendor.Sys.Services.ReceiveNoteData receiveNoteData)
{
this._ReceiveNoteData = receiveNoteData;
}
public abstract Vendor.Sys.Services.ReceiveNoteResponse TakeAction(Vendor.Sys.Services.ReceiveNoteData receiveNoteData);
}
}
Implementation of the abstract class:
public class Sys2Handler : NoteReceiverHandler
{
public override Vendor.Sys.Services.ReceiveNoteResponse TakeAction(Vendor.Sys.Services.ReceiveNoteData receiveNoteData)
{
return new Vendor.Sys.Services.ReceiveNoteResponse();
}
Am I just overlooking something? This happens even when I use "Quick Actions and Refactorings" to generate the abstract class.
The following code providing all classes have the same public accessibility compiles perfectly when in single or multiple assemblies.
namespace StandardNoteReceiverService
{
public abstract class NoteReceiverHandler : BaseIntegrationService
{
private Vendor.Sys.Services.ReceiveNoteData _ReceiveNoteData;
public NoteReceiverHandler() { }
public NoteReceiverHandler(Vendor.Sys.Services.ReceiveNoteData receiveNoteData)
{
this._ReceiveNoteData = receiveNoteData;
}
public abstract Vendor.Sys.Services.ReceiveNoteResponse TakeAction(Vendor.Sys.Services.ReceiveNoteData receiveNoteData);
}
public class Sys2Handler : NoteReceiverHandler
{
public override Services.ReceiveNoteResponse TakeAction(Services.ReceiveNoteData receiveNoteData)
{
throw new NotImplementedException();
}
}
}
The only problems which may prevent compilation are different accessibility modifiers or different/conflicting type identity which by .NET is defined as:
Type name, Assembly Name, Assembly Version, Assembly Public Key Signature
Make sure all dependency tree is correct, accessibility is the same and try to recompile. Satisfying the first condition could be a challenge for large projects so perhaps you should use a dependency tree walker to check that all dependencies are correct.
Keep in mind that proper versioning may save you from many similar errors particularly in large code bases.
This can possibly happen if your assemblies are targeting different .net Framework versions.
I'd double check project settings for each assembly.
I have created a .cs files that contain the following:
namespace SetUp
{
class Config
{
public static object SetConfig(int code, bool print)
{
//My Code
}
}
}
Compiled it and added the reference to my main project called 'CSharp Side', for example. Added it to my project and everything is great. But my question is how do I access 'SetConfig()'? Because it doesn't recognize 'SetUp' or 'Config' in my code.
Simply make your class as public.
namespace SetUp
{
public class Config
{
public static object SetConfig(int code, bool print)
{
//My Code
}
}
}
You can reference code in a different assembly by fully qualifying:
SetUp.Config.SetConfig(1, true);
or include the namespace with a using directive:
using SetUp;
class SomeClass
{
void SomeMethod()
{
Config.SetConfig(1, true);
}
}
Also, both the class and the method in the referenced assembly need the public modifier. Otherwise they won't be visible outside the assembly where they are defined.
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 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.
I see this question a fair amount on SO, and I've followed that advice, but I appear to be doing something wrong. The dll seems to load in fine but the object CreateInstance is returning is null.
I have this dll:
namespace Backfill
{
public class Module : Kernel.Module
{
public override void ModuleStart()
{
//Stuff
}
}
}
In another DLL with a DIFFERENT namespace
namespace Kernel
{
public abstract class Module
{
public abstract void ModuleStart();
}
public static void KernelStart()
{
string load_dll = #"Path to DLL";
Assembly test_dll = Assembly.LoadFile(load_dll + ".dll");
Module test_mod = (Module)test_dll.CreateInstance("Kernel.Module");
test_mod.ModuleStart();
}
}
(Module)test_dll.CreateInstance("Kernel.Module"); is returning null, though. Any idea why?
(Module)test_dll.CreateInstance("Kernel.Module")
This won't work. As you specified, the Module class which you're trying to instantiate (which, I assume, is the one from the first DLL), is not in the Kernel namespace, but in the Backfill namespace. You should therefore have something along these lines:
(Module)test_dll.CreateInstance("Backfill.Module")
Kernel.Module is an abstract class. You cannot create an instance of it directly. You need to create an instance of the derived class.
Edit: Since supplying more info:
#Antonijn has the same answer. You need to specify the type that you want directly. BackFill.Module seems like the correct one.
Before Edit:
If you have the same names in multiple assemblies then yo need to use a fully qualified (including assembly name) for the type you want. For exmaple: https://stackoverflow.com/a/2300428/30225 as an possible answer.