How to read class attribute on Windows Phone? - c#

How can I read attribute of a class in Windows Phone?
public static void DoSth<T>(T sth)
where T : SomeClass
{
MyAttribute a = // Get "MyAttribute" from sth
}

Reflection works somewhat differently in .NET for Windows Store apps. You probably have to access this through System.Reflection.TypeInfo like so:
MyAttribute a = typeof(T).GetTypeInfo().GetCustomAttribute<MyAttribute>()
This article explains some of the differences in the Reflection APIs and why they exist.
In short, the authors wanted to expand the scenarios for Reflection and the design they settled on has a sort of "light-weight" Type class and a "heavy-weight" TypeInfo class. However for backwards compatibility in the full framework Type can still be used in the old heavy-weight way. On .NET for Windows Store, they had the chance make a single consistent API so they did that. Therefore Reflection code that works on .NET for Windows Store works in the full .NET framework but not the other way around.

Related

Appdomain not woking with .net 6? [duplicate]

Is there a strong reason why Microsoft chose not to support AppDomains in .NET Core?
AppDomains are particularly useful when building long running server apps, where we may want to update the assemblies loaded by the server is a graceful manner, without shutting down the server.
Without AppDomains, how are we going to replace our assemblies in a long running server process?
AppDomains also provide us a way to isolate different parts of server code. Like, a custom websocket server can have socket code in primary appdomain, while our services run in secondary appdomain.
Without AppDomains, the above scenario is not possible.
I can see an argument that may talk about using VMs concept of Cloud for handling assembly changes and not having to incur the overhead of AppDomains. But is this what Microsoft thinks or says? or they have a specific reason and alternatives for the above scenarios?
The point of the .NETCore subset was to keep a .NET install small. And easy to port. Which is why you can, say, run a Silverlight app on both Windows and OSX and not wait very long when you visit the web page. Downloading and installing the complete runtime and framework takes a handful of seconds, give or take.
Keeping it small inevitably requires features to be cut. Remoting was very high on that list, it is quite expensive. Otherwise well hidden, but you can for example see that delegates no longer have a functional BeginInvoke() method. Which put AppDomain on the cut list as well, you can't run code in an app domain without remoting support. So this is entirely by design.
Update for .NET Standard 2 and .NET Core 2
In .NET Standard 2 the AppDomain class is in there. However, many parts of that API will throw a PlatformNotSupportedException for .NET Core.
The main reason it's still in there is for basic stuff like registering an unhandled exception handler which will work.
The .NET Standard FAQ has this explanation:
Is AppDomain part of .NET Standard?
The AppDomain type is part of .NET Standard. Not all platforms will support the creation of new app domains, for example, .NET Core will not, so the method AppDomain.CreateDomain while being available in .NET Standard might throw PlatformNotSupportedException.
The primary reason we expose this type in .NET Standard is because the usage is fairly high and typically not associated with creating new app domains but for interacting with the current app domain, such as registering an unhandled exception handler or asking for the application's base directory.
Apart from that, the other answer and other answers also nicely explain why the bulk of AppDomain was still cut (e.g. throws a not supported exception).
App Domains
Why was it discontinued? AppDomains require runtime support and are generally quite expensive. While still implemented by CoreCLR, it’s not available in .NET Native and we don’t plan on adding this capability there.
What should I use instead? AppDomains were used for different purposes. For code isolation, we recommend processes and/or containers. For dynamic loading of assemblies, we recommend the new AssemblyLoadContext class.
Source: Porting to .NET Core | .NET Blog
You don't need AppDomains anymore, you now have LoadContexts:
public class CollectibleAssemblyLoadContext
: AssemblyLoadContext
{
public CollectibleAssemblyLoadContext() : base(isCollectible: true)
{ }
protected override Assembly Load(AssemblyName assemblyName)
{
return null;
}
}
byte[] result = null; // Assembly Emit-result from roslyn
System.Runtime.Loader.AssemblyLoadContext context = new CollectibleAssemblyLoadContext();
System.IO.Stream ms = new System.IO.MemoryStream(result);
System.Reflection.Assembly assembly = context.LoadFromStream(ms);
System.Type programType = assembly.GetType("RsEval");
MyAbstractClass eval = (MyAbstractClass )System.Activator.CreateInstance(programType);
eval.LoadContext = context;
eval.Stream = ms;
// do something here with the dynamically created class "eval"
and then you can say
eval.LoadContext.Unload();
eval.Stream.Dispose();
Bonus if you put that into the IDisposable interface of the abstract class, then you can just use using, if you want to.
Note:
This assumes a fixed abstract class in a common assembly
public abstract class MyAbstractClass
{
public virtual void foo()
{}
}
and a dynamically runtime-generated class ( using Roslyn), referencing the abstract class in the common assembly, which implements e.g.:
public class RsEval: MyAbstractClass
{
public override void foo()
{}
}
At one point, I heard that unloading assemblies would be enabled without using domains. I think that the System.Runtime.Loader.AssemblyLoadContext type in System.Runtime.Loader.dll is related to this work, but I don't see anything there that enables unloading yet.
I have heard in a community standup or some talk of Microsoft that the isolation feature of AppDomains are better handled by processes (and actually the common pattern in other platforms) and the unloading is indeed planned as a normal feature unrelated to AppDomains.

Checking to see if you can call methods from an api before calling it

I have the following code:
var view = ApplicationView.GetForCurrentView();
var runtimeMethods = view.GetType().GetRuntimeMethods();
if (!view.IsFullScreen)
{
var tryEnterFullScreenMode = runtimeMethods.FirstOrDefault(
x => x.Name == "TryEnterFullScreenMode");
tryEnterFullScreenMode?.Invoke(view, null);
}
What this does is cause my application to become fullscreen however if I'm on a windows 8.1 pc I can't call these methods. How can I first check to see if this functionality is available before calling the methods. Will I use #if...#endif?
Basically I would like to only use this code when the app is running on a machine that has access to it(Windows 10 operating system).
Desktop development doesn't suffer from fragmentation experienced by web development, therefore there is no feature support query, rather library support/os version. Nor that I know, at least.
What usually done is
1) Dynamic loading of assemblies, based on the OS family version you are running on. For that you need some common interface wrapper, that holds inside, under the hood, all "real" API calls.
2) Have distinct version for every different OS family. You need to support 2 code bases. Event though, the code that actually different may be moved to separate assembly, so you have only small set of assemblies that are different between different families of OSes. Good for patching, as only relatively small amount of data has to be moved to the client. Still common interface is required here.
So the basic question you have to find answer is: not how to handle diversity, but rather, what you should do once you find that you need to do something different from expected. From that you can understand most reliable way you are going to handle it.
You can use essentially that code on a Windows 8.1 system. On Windows 10 tryEnterFullScreenMode will be set. On Windows 8.1 it will be null. Invoke the method only if it is set:
var view = ApplicationView.GetForCurrentView();
TypeInfo t = typeof(ApplicationView).GetTypeInfo();
var tryEnterFullScreenMode = t.GetDeclaredMethod("TryEnterFullScreenMode");
if (tryEnterFullScreenMode != null)
{
tryEnterFullScreenMode.Invoke(view, null);
}
Windows 10 introduces proper feature support so you don't to fall back on reflection. You can check if a Contract or API exists with Windows.Foundation.Metadata.ApiInformation. This allows checking for features that are device specific or version specific and then easily calling them with normal syntax (rather than reflection syntax) if they are present. The check can be based on contract, type, or individual method, property, or event:
// Useless example since TryEnterFullScreenMode is in the UniversalApiContract
// and so guaranteed to be there in all Windows 10 apps
bool isEnterFullScreenPresent = Windows.Foundation.Metadata.ApiInformation.IsMethodPresent("Windows.UI.ViewManagement.ApplicationView", "TryEnterFullScreenMode");
if (isEnterFullScreenPresent)
{
ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
}
For more on API Contracts and feature detection see the Guide to Universal Windows Platform (UWP) apps on MSDN.

Portable Class Library Profile 78 missing attribute related methods/properties

In my PCL core project (WP8, Android, iOS, Xamarin, MvvmCross) I use custom attributes. The Type.GetCustomAttributes() extension method lets me examine the attributes used.
Using PCL Profile104 this works well. But because I want to use async/await, I'll need to use PCL Profile78 (and .NET 4.5)
Problem: Seems the GetCustomAttributes() and the Attributes property are not available in Profile78. Why??
Note:
I am looking into the workaround by creating a PCL Profile 104 class library and wrapping the GetCustomAttributes() and then referencing this library from my PCL Profile78 library. However it seems extensionmethods are not supported...
Example Code:
public Pcl78Class()
{
Type t = this.GetType();
var attributes = t.Attributes;
var customAttributes = t.GetCustomAttributes(true);
// another weird thing: Why is VS CodeCompletion telling me it knows CustomAttributeExtensions class and methods?
//System.Reflection.CustomAttributeExtensions.GetCustomAttributes(t);
}
Problem: Seems the GetCustomAttributes() and the Attributes property are not available in Profile78. Why??
Profile78 includes support for Windows Store 8 (as noted on my blog), and Windows Store has a more efficient implementation of Type-based reflection. Essentially, you just have to call Type.GetTypeInfo to get a TypeInfo, and from there it should be pretty straightforward.

Provide limited API externally as DLL

If you had to expose functionality externally as a DLL but only a subset of functionality (meaning you can't provide a core DLL as it would expose everything) how is best to do this?
At the moment I can't really see any way of doing it that doesn't involve recreating the parts of the core library in a seperate DLL.
You could use internal along with Friend Assemblies. Your API can be a friend of the core library allowing access to internal members.
See here for more details - http://msdn.microsoft.com/en-us/library/0tke9fxk(v=vs.90).aspx
This would allow you to keep your core objects internalised whilst allowing the API access to them.
Note that you will STILL need to supply the core library. There's no way around this unless you use something to merge the .NET assemblies or you compile the code into your API library.
However I think this is a bad idea and you should keep such entities separate. I don't see why there is an issue shipping more than one library thesedays.
FYI - ILMerge will let you merge .NET assemblies, you can get it from here - http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx
Surely by just creating a new project that wraps the core DLL, exposing only the methods you want exposed, each of which is acting more or less as a "pass-through" to the "Same" method in the core?
So if you core is called Core :)
it might have:
public int Foo()
{
//blah
}
public int Bar()
{
/blah
}
and if you want to only expose Foo, then you create a new project which references Core, and looks like this:
using Core;
public class MyApi
{
private Core _coreInstance.... //some way of reaching Core, in other words
public int Foo()
{
return _coreInstance.Foo();
}
}
An advantage of creating a separate assembly here is that you are then treating your core functionality as one concept, and the exposure of it publicly (to a particular purpose or audience) as another. You may very well want to expose "publicly" different functionality at a later stage, but to a different audience - you now have 2 different public APIs required: therefore any notion of what was "public" in your core assembly is now potentially ambiguous.
I think it depends on the aims you follow in hiding the core libraries.
If you don't want to allow your customers to call the code, for example if that may break usage scenarios of your libraries, or may cause undesirable behavior, or whatever to prevent CALLING the code, you can make the protected classes internal, and use InternalsVisibleToAttribute to include the Facade assembly. I would even use one more build configuration if I still needed core classes to be visible in my applications:
#if PUBLIC_BUILD
internal
#else
public
#endif
class ProtectedCoreClass
But of course if you have too many classes, some script should be prepared to change the existing classes, and Visual Studio's new class template should be modified.
But another case is if you want to prevent the source code from being WATCHED by your customers in order to hide some super unique algorithms or something. Then you should look into some code obfuscator. But there is absolutely no way to 100% guarantee the code from being decompiled and analyzed. It's only about the price crackers or competitors pay for it.
But if HIDING the source code is still extremly important, you should probably just host your code on your servers (to make sure the code is physically inaccessible) or in the cloud, and provide a WCF or a web service your exposing assembly will call.

.NET: with respect to AssemblyVersion, what defines binary compatibility?

What changes to a strong-named assembly necessitate a change in AssemblyVersionAttribute? Clearly, changing the public api in a way that could require a client to have to make a code change requires an increase in AssemblyVersion. But what about changes to the public API that don't require code changes in the client? For instance:
the addition of a public class or interface?
the addition of a public member to a public class or interface? (EDIT: drscroogemcduck correctly points out below that adding a member to an interface would hose all implementors. Silly me.)
an increase of visibility of a class member?
There's got to be definitive documentation of this somewhere on MSDN (or, knowing MS, on some MSSE's personal blog). But I simply cannot find it. Please help!
In response to Martijn's bounty:
The best reference on binary compatibility is on the community Wiki.
A definite guide to API-breaking changes in .NET
It's pretty easy... as long as Types remain unchanged (in their public or protected layout) and method signatures are not changed (adding methods or types is fine), the JIT should be able to link the DLL just fine.
That said, I think that even if it does work you should not do this. Make a new version and use a policy to map the old version to the new one, if required. Otherwise you drive yourself straight back to DLL hell... and I'm pretty sure you don't want that.
adding methods to an interface shouldn't be fine because old providers won't implement the new methods.
Microsoft adds new methods/classes in .NET libraries in service pack releases without changing AssemblyVersion (still 2.0.0.0 / 3.0.0.0). Microsoft only changes the AssemblyFileVersion.
For example, In .NET 2.0 SP1, DateTimeOffset struct was added.
Should this practice be recommended to us because Microsoft do this?
It is confusing.

Categories