quick theoric question. I have the following code:
if (partnership != null && partnership.UseCustomNotifier)
{
//some behavior
}
else
{
Integration.Protocol.Client.Notifier protocolNotifier = new Integration.Protocol.Client.Notifier();
}
I have two implementations for partnership that are chosen using reflection. Integration.Protocol is not in the usings. Implementation should be chosen dynamically; thing is, if I comment that last line (the instantiation of protocolNotifier), it will only chose one implementation (the one that does not come from the Integration.Protocol, because is the only one available). Otherwise, it will be chosen dynamically using reflection.
I know that this code sucks (I've improved it already), but I was curious on why this behavior was ocurring. I would guess that when the solution compiles before running, it checks that line where protocolNotifier is instantiated and adds the using on compilation time. Is this correct? Does it only happen within the scope of the method? Or the whole class? I am curious on how the .NET compiler works in those situations.
If I understand you correctly:
partnership is an object of a type that is chosen by using reflection to find all available classes with that name (we'll call it Partnership) and creating an object of the found type
The Integration.Protocol namespace has a class called Partnership (or whatever it's actually called), but there is also another class called Partnership in either this project's code or some other library that you're already using elsewhere
Depending on if you include that last line or not, your reflection code picks one or the other
If I'm correct in that, then I believe the behaviour you're seeing is simply because it's loading the Integration.Protocol library (assuming that is a separate DLL and not actually part of the current project code).
If you show us the code of how you set partnership, then we can confirm this. But if I'm correct, then if you don't use Integration.Protocol in that last line, then that library simply isn't loaded, and your reflection code won't find anything from that library.
It's not that "adding the using on compilation time", because using statements just allow you to not include the namespace when referring to classes. It doesn't have anything to do with whether libraries are loaded at runtime or not.
Related
Say I have two methods, one calls the other. The second method has code that will generate a compile time error. Since it's not called, why does the compiler still bother to process it?
void method1()
{
var i = 1;
//method2();
}
void method2()
{
int i = "2";
}
You can't be sure that someone else won't call that method at runtime using reflection. Your code MUST compile or it's not valid code - if it's never used... comment it out!
To expand on this:
Basically at compile time you are strongly typed - .NET will type check everything to ensure that what you are trying to do is legal, however, you can still throw exceptions at run time due to null references, bad casts etc etc.
Reflection is a component of the .NET framework that allows a developer to inspect the properties/fields/methods etc of an assemblies types via the assembly metadata
Reflection allows runtime type discovery and inspection of these types, it also allows invocation of methods/properties and modification of fields etc. (You can even create new generic types at runtime or completely new types altogether).
In other words, you can't guarantee that code you think won't be called, isn't called somewhere else at some point. For reflection to be possible, every bit of code needs to be valid and compilable
Whether that code will succeed at runtime is another story - but that's why we have exception handling.
And then what if somebody else uses your compiled code later on and decides to use it?
Even with private methods Reflection can complicate matters.
If you don't use it, lose it. (or at least comment it out)
Well, it's clear for me that the title of my question is too complicated. I just tried to make it as specific as possible. So, I'll try to explain the problem better.
Problem context
Let's assume we have three .NET projects in a solution. The main project is a simple console application ApplicationAssembly. This project has a reference to another managed assembly library DirectlyReferencedLibrary. At the same time DirectlyReferencedLibrary refers to IndirectlyUsedLibrary.
So, the project usages looks like that:
ApplicationAssembly --> DirectlyReferencedLibrary --> IndirectlyUsedLibrary.
Notice that ApplicationAssembly doesn't use directly any type declared IndirectlyUsedLibrary. Let's also assume that all types declared in these assemblies reside in the same namespace.
This solution compiles and works fine.
Weird problem
The problem occurs when I have together the following conditions:
the ApplicationAssembly project has usages of LINQ expressions. For example, if there is the invocation of Select() on any object of enumerable type.
The DirectlyReferencedLibrary declares a class which has a generic extension method with a type restriction. The type restriction says that the generic type must be a descendant of a class from the IndirectlyUsedLibrary.
Here is the example of a such class.
using System;
namespace Test
{
public static class UnUsedType
{
// It's a generic extension method with a type restriction.
public static void Magic<T>(this T #this)
// It's a type restriction that uses a type from the IndirectlyUsedLibrary.
where T : ProblemType
{
Console.WriteLine("I do nothing actually.");
}
}
}
When I try to compile this project, I get the following error:
Error The type 'Test.ProblemType' is defined in an assembly that is not referenced. You must add a reference to assembly 'IndirectlyUsedLibrary, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'. C:\Projects\Test\ApplicationAssembly\Program.cs 22 13 ApplicationAssembly
Question
Can anyone help me to understand why is it so?
P.S.
I've made a tiny solution for investigation. If you are so kind to help me, you will be able to take an archived solution here
P.P.S.
Sorry for my poor English.
UPD1
Another strange thing is that different invocations of the LINQ method may or may not produce the compile time error:
// Ok. Let's do some work using LINQ we love so much!
var strings = new[] { "aaa", "bbb", "ccc" };
Func<string, object> converter = item => (object) item;
// The following line makes problems.
var asObjects1 = strings.Select(converter);
// Everything is OK if we use the following line:
var asObjects2 = Enumerable.Select(strings, converter);
Can anyone help me to understand why is it so?
The C# compiler has the reasonable expectation that the transitive closure of the referenced assemblies is available at compile time. It does not have any kind of advanced logic that reasons about what it definitely needs, might need, might not need, or definitely does not need to know in order to solve all the problems in type analysis that your program is going to throw at it. If you reference an assembly directly or indirectly, the compiler assumes that there might be type information in there that it needs.
Also, if you don't have the set of referenced assemblies at compile time then what expectation is there that users will have them at runtime? It seems reasonable to expect that the compile time environment has at least the set of assemblies that are going to be required at runtime.
I don't want to do it.
We all have to do things we don't want to do in life.
I think you knew this, but because the type ProblemType is defined in the "IndirectlyUsedLibrary" but is a required definition for the Magic extension method it must be referenced to be available at compile time.
As to "why"... Well, the compiler needs to know details about what it's compiling doesn't it? It makes sense to me that the compiler require the same minimum set of compile time references that it requires at run time...
You'll not have an error if you use different namespaces for libraries. It's really wierd to use same namespace across different libraries.
Looks like compiler starts scanning your Test namespace for extensions once you first time use any. Hence the reference is required.
I inherited some source code that I am just starting to dig though, and i found the previous owner has made some use of the using directive as an alias for a List<T>, but I've never seen this specific approach before.
namespace MyNamespace
{
using pType1 = List<type1>;
using pType2 = List<List<type1>>;
// classes here
}
Both of these elements are used quite heavily within the code and are also return types from several of the key methods within the code. I get what he was trying to accomplish with using a simple name rather than repeating List<type1> and List<List<type1>> over and over again. I'm debating whether to create a real type to replace the using statements, but before i spend the time, I was wondering if there were any pros/cons to keeping the current implementation.
Generally, if a data structure represents some entity in your application's domain model it should get its own type; it makes the code much clearer and understandable. On the other hand, if you just need a List<List<string>> for intermediate data processing there's no real benefit in making a proper type for that.
In your case, since the original dev went to the trouble of making an alias for the type it's logical that it would be used a lot, which points to the "represents an entity" scenario. If so, definitely go ahead and create a new type for the structure (possibly something more appropriate than bare lists and usually something defined in terms of interfaces rather than concrete classes, but that depends on what you 're actually modelling there).
If that construct is used as heavily as you say, I would definitely replace it with (the) real types (explicitly write out the List or create a new type). If someone happens to change one of the type declarations, like
using pType1 = List<type2WhichType1InheritsFrom>;
because (s)he thinks the base version does something better without looking at all places where it is used, there might be some unwanted side effects.
I have fields in one class and I want to move them to another class. Creating the new fields is not that much work. Changing all their references from the class they were in until now, however - is.
‘Rename’ doesn’t accept ‘myClass.Field’ as valid. Is changing using Find-and-Replace the only option (though then I’ll have to check every occurrence because of identically-named variables)? Or is there a simple way like ‘Rename’?
There is no (built-in) refactoring that will move a variable to another type. Some third party refactoring tools (such as Resharper) do include this as additional features.
However, I would recommend letting the compiler help you instead of relying on Find and Replace. If you remove the original variables, every access of the variable will become an instant compiler error. This will give you all of the usages without false positives.
Here is what I would do:
1. Ensure everything compiles well first :)
2. Move your variable into the new class MyClass
3. Add a field MyClass myClass to the original class and instantiate it in the constructor
4. Using a text editor (as VS does not allow this) search for all instances of Field and replace them by myClass.Field
5. Back to VS, compile your code again
This should work fine and should save you some valuable time.
Regards,
For example:
[TestFixtureSetUp]
public void Init()
{
GetTestRepo(false);
}
[TestFixtureSetUp] in this example, what does it do? From my experience, [] usually refers to lists.
Attributes. They are a way to add metadata about methods/properties/interfaces/classes/namespaces for inspection at runtime.
Your example adds the TestFixtureSetUpAttribute to a method. This allows the test runner to determine which method in your class to run when setting up a text fixture.
The test runner loads your test assembly into memory at runtime. It then enumerates through the classes defined within your assembly that have been marked with a particular attribute (whatever NUnit uses to mark a test class). The runner now knows what classes to instantiate to run tests. It then looks through the methods defined in the class for a method that will be run to set up the test fixture. It searches each method for the attribute you asked about. Once it finds that method it knows to run that method before running tests/each test (whichever it means in NUnit).
Attributes are all about adding information about a method that you can search for at runtime. Its the kind of thing where if you don't need 'em you don't miss 'em, but when you DO need 'em OMFG is it great that they're available.
(In C#, you can omit the "Attribute" from the type name. The compiler knows you're talking about, for instance, "SerializableAttribute" when you say [Serializable])
Attributes. You can find more information here.
It is an Attribute
It's an attribute. Sort of like MetaData for the class/function you use it on.
They are called attributes (analogous to Java annotations) and they are compiled in as meta data.
You appear to be recreating a basic VB/C# faq by asking one question at a time in SO. To add to that, it does appear to be a good way to get reputation.
To answer the TITLE, [] are the symbols used to
index into arrays
enclose an attribute (metadata) on a method
one other thing I can't remember
VB.Net uses the <> characters for the same purpose on metadata, but uses () to indicate array access.
Java uses a leading "#" for the same purpose
If you didn't have those special characters, the compiler couldn't interpret what you wrote. Not sure what else you want to know. Do you want to know the meaning of TestFixture?