I have:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class FooAttribute : Attribute
{
}
[Foo]
public class Bar1
{
}
[Foo]
public class Bar2
{
}
[Foo]
public class Bar3
{
}
Then I do:
var attrs = CustomAttributeExtensions.GetCustomAttributes(typeof(Bar1).GetTypeInfo().Assembly);
I had expeced that attrs should contain the Foo attribute,, but that is not true. Instead attrs contains 12 other attributes.
Whats wrong??
Maby not plesant,,, but Hans answer workes for me.
If you want to find all of the types that have a this attribute then you have to enumerate the types in the assembly, Assembly.GetTypes(). Tough cookies on winrt. – Hans Passant 20 hours ago
Related
I am returning a list of products of type ListProd in my Spring Boot controller, and such object has a nested property of type List<Product> ... something like this:
public class Product implements Serializable {
int codProdct;
String dsc;
public Product(){};
// plus getters and setters (omitted for simplicity)
}
public class ListProd implements Serializable {
int codList;
List<Product> products;
public ListProd(){};
// also here getters and setters
}
and in my angular project I have the next analogoust entities:
export class Product {
public codProduct:number;
public dsc:string;
constructor(){
codProduct=null; //just for completness
dsc='';
}
}
export class ListProd {
public codList:number;
public products:Product[];
constructor(){
this.codList=null; //just for completness
this.products=null;
}
}
I'm sending a ListProd object through my Spring controller and Angular gets such an object correctly and assigns the type also correctly:
return this.http.get<ListProd>(this.apiUrl + "/getListProds", httpOptions);
but ... it is only casting correctly the parent object, when I check the type of the 'products' object (which is recived correctly, only untyped) y get type: Object
I tried to make it a Products[] in my ListProd class in java, but i get the same result. I don't know much about the 'magic' Angular does to assign those types properly, am I missing something important here? Is there a chance to force the casting on the Angular side?
Thanks in advance.
Well, if ListProd is supposed to hold array of Product[] there is a typo here.
public products:Product[];
Not knowing full extent why you use class over an interface I would advise you also to go over this. Maybe there is a reason but for being able to strong type simple interface would be better. https://www.javatpoint.com/typescript-class-vs-interface
{"country":{"code":"NZ"}}
How would you store this data in a unity class?
Something like this:
using UnityEngine;
using System;
using System.Collections;
using System.Globalization;
[Serializable]
public class GDRPClass
{
public string country;
public string code;
}
I dont think that is right for a double {} though.
Thanks
Always a very good starting point: json2csharp!
just make sure to use fields instead of properties and mark the clases [Serializable]:
[Serializable]
public class Country
{
public string code;
}
[Serializeable]
public class GDRPClass
{
public Country country;
}
You can call the classes/structs whatever you like, but the field names have to match!
In this simple case the structure is easily explained since the data types in JSON are very limited. You can see it better if you use the intended notation
{
"country" :
{
"code" : "NZ"
}
}
{ } in json always wrap a json object (= class/struct). So you already know there have to be exactly two class/struct types in your case.
you can see the first (root) type has to have one field called country. This field's type is the other class/struct's type.
this second inner type has another field called code. It's type is a string.
And that's exactly what json2csharp already spit out for us ;)
Now you can e.g. use JsonUtility.FromJson
var json = "{\"country\":{\"code\":\"NZ\"}}";
var jsonObject = JsonUtility.FromJson<GDRPClass>(json);
and later access the data using e.g.
var code = jsonObject.country.code; // = "NZ"
"country" is basically used as a key for "{"code":"NZ"}", so they're on different levels of the tree.
You could deserialize this into a Dictionary<string, CountryInfo> (but not with with the built-in JsonUtility, that doesn't do Dictionaries, so I used Json .Net instead)
Have a look:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
public class TestDeserialize : MonoBehaviour {
[SerializeField] private string m_JsonStr = "{\"New Zealand\":{\"code\":\"NZ\"}}";
void Start() {
Dictionary<string,CountryInfo> result = JsonConvert.DeserializeObject<Dictionary<string, CountryInfo>>(m_JsonStr);
foreach (KeyValuePair<string,CountryInfo> country in result) { //Log results
Debug.LogFormat("{0}: {1}", country.Key, country.Value.code);
}
Debug.Log(JsonConvert.SerializeObject(result)); //Serializes back into its original form
}
[Serializable]
class CountryInfo {
public string code;
}
}
I use Pathfinding.Serialization.JsonFx for JSON Parsing
{\"country\":4,\"code\":\"Afghanistan\"}
This will be the jsonString with respect to your Model class
GDRPClass data = JsonReader.Deserialize<GDRPClass>JsonWriter.Serialize(jsonString));
I'm kinda new to JSON but managed to handle the concept for quite a while on # until I stumbled on this problem.
In the background, I receive a JSON string that I cannot change and of which I do not have the class definition. So I have to mimic them to deserialize first.
Basically, most of the time, I deserialize lists like
"table" : [
{object},
{object}
]
And I'm fine.
Though
I found this architecture in a corner of the string I receive:
"list" : {
"item1":{object},
"item2":{object},
"item2":{object},
...
}
And as this list is pretty big, I'm quite annoyed to have to reproduce the structure into a rigid class like:
public class itemClass
{}
public class list
{
public ItemClass item1;
public ItemClass item2;
public ItemClass item3;
...
}
My question is : Is there a way to interpret all the items as a list instead and use the tag they have in front as the value of an attribute ?
So basically, can I serialize an attribute so that it becomes the title of the seralized item and backwards ?
I could automatize and my life would get easier.
is there anything like:
public class ItemClass
{
[magic JSON attribute that transforms this attribute's value into the title of the serialized string]
public string title;
public int otherValues;
}
public class list
{
public List<ItemClass> items;
}
I hope you have some ideas to share.
Thanks
I am confused by Castle Windsor resolve method. This method allows me to pass almost anything. Is the value submitted in the resolve method passed along and used in the constructor of the object which is eventually resolved to, or is this value used to help the resolver determine what concrete implementation to use?
For example, if I have the following snippet...
var _container = new WindsorContainer();
_container.Install(FromAssembly.This());
var MyProcessor = _container.Resolve<IProcessor>(new Arguments(new {"Processor1"}));
assuming I have two concrete implementations of IProcessor - like Processor1:IProcessor, and/or Processor2:IProcessor. What are the 'Arguments' used for?
I understand the...
Component.For<IProcessor>()
... needs to be defined, but I am struggling with the terms the Windsor folks choose to use (i.e. DependsOn, or ServicesOverrides) and the intent. Given the method is called 'resolve' I can only image any values passed to this will be used to resolve the decision on which concrete implementation to use. Is this assumption wrong?
The arguments parameter you're talking about is for providing arguments to components that can't be satisfied by Windsor components. The anonymous types overloads as well as the dictionary overalls I believe are all for this purpose. I've used this in the past, and I don't recommend it as it leads to poor patterns like Cristiano mentioned... and last time I used this it only works for the component being directly resolved. Anyway... here's an example of how this works:
[TestFixture]
public class Fixture
{
[Test]
public void Test()
{
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>().LifeStyle.Is(LifestyleType.Transient));
Assert.Throws<HandlerException>(() => container.Resolve<IFoo>());
IFoo foo = container.Resolve<IFoo>(new {arg1 = "hello", arg2 = "world"});
Assert.That(foo, Is.InstanceOf<Foo>());
Assert.That(foo.ToString(), Is.EqualTo("hello world"));
}
}
public interface IFoo
{
}
public class Foo : IFoo
{
private readonly string _arg1;
private readonly string _arg2;
public Foo(string arg1, string arg2)
{
_arg1 = arg1;
_arg2 = arg2;
}
public override string ToString()
{
return string.Format("{0} {1}", _arg1, _arg2);
}
}
I am awarding the answer to kellyb for the awesome example. During investigation, using Castle.Windsor 3.2.1, I found at least 2 reasons for passing a value in the "resolve" method.
To satisfy intrinsic type dependencies, such as strings, or integers in
the object resolved by the use of the "Resolve" method - as
described in kellyb's example.
To help Castle identify which concrete implementation to select.
to help illustrate both uses I am elaborating on the example provided above by kellyb.
Synopsis - or test condition
Assume there is one interface called IFoo and two concrete implementations that derive from this interface called Foo and Bar. A class called Baz is defined but does not derive from anything. Assume Foo requires two strings, but Bar requires a Baz.
Interface IFoo Definition
namespace CastleTest
{
public interface IFoo
{
}
}
Class Foo Definition
namespace CastleTest
{
public class Foo : IFoo
{
private readonly string _arg1;
private readonly string _arg2;
public Foo(string arg1, string arg2)
{
_arg1 = arg1;
_arg2 = arg2;
}
public override string ToString()
{
return string.Format("{0} {1}", _arg1, _arg2);
}
}
}
Class Bar Definition
namespace CastleTest
{
class Bar : IFoo
{
private Baz baz;
public Bar(Baz baz)
{
this.baz = baz;
}
public override string ToString()
{
return string.Format("I am Bar. Baz = {0}", baz);
}
}
}
Class Baz Definition
namespace CastleTest
{
public class Baz
{
public override string ToString()
{
return "I am baz.";
}
}
}
The Test (Drum roll, please!)
kellyb's example test shows an assert that expects a failure if args is not supplied. kellyb's example does not have multiple implementations registered. My example has multiple implementations registered, and depending on which is marked as the default this assert may or may not fail. For example, if the concrete implementation named "AFooNamedFoo" is marked as default, the assert completes successfully - that is to say the resolution of an IFoo as a Foo does indeed require args to be defined. If the concrete implementation named "AFooNamedBar" is marked as default, the assertion fails - that is to say the resolution of an IFoo as a Bar does not require args to be defined because its dependency of a Baz is already registered (in my example where multiple concrete implementations are registered). For this reason, I have commented out the assert in my example.
using Castle.Core;
using Castle.MicroKernel.Handlers;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NUnit.Framework;
namespace CastleTest
{
[TestFixture]
public class ArgsIdentifyConcreteImplementation
{
[Test]
public void WhenSendingArgsInResolveMethodTheyAreUsedToIdentifyConcreteImplementation()
{
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>().LifeStyle.Is(LifestyleType.Transient).Named("AFooNamedFoo"));
container.Register(Component.For<IFoo>().ImplementedBy<Bar>().LifeStyle.Is(LifestyleType.Transient).Named("AFooNamedBar").IsDefault());
container.Register(Component.For<Baz>().ImplementedBy<Baz>().LifeStyle.Is(LifestyleType.Transient));
// THIS ASSERT FAILS IF AFooNamedBar IS DEFAULT, BUT
// WORKS IF AFooNamedFoo IS DEFAULT
//Assert.Throws<HandlerException>(() => container.Resolve<IFoo>());
// RESOLVE A FOO
IFoo foo = container.Resolve<IFoo>("AFooNamedFoo", new { arg1 = "hello", arg2 = "world" });
Assert.That(foo, Is.InstanceOf<Foo>());
Assert.That(foo.ToString(), Is.EqualTo("hello world"));
// RESOLVE A BAR
IFoo bar = container.Resolve<IFoo>("AFooNamedBar");
Assert.That(bar, Is.InstanceOf<Bar>());
Assert.That(bar.ToString(), Is.EqualTo("I am Bar. Baz = I am baz."));
}
}
}
Conclusion
Looking at the test above, the resolution of a Foo object has two things passed in the "resolve" method - the name of the implementation, and the additional string dependencies as an IDictionary object. The resolution of a Bar object has one thing passed in the "resolve" method - the name of the implementation.
In fact you should not call Resolve ever in your code rather than in the Composition root and also there you should not need to supply parameters to the Resolve method.
Custom resolution strategies should be done through installers, factories/ITypedFactoryComponentSelector, subresolvers... see documentation for more details on those options
BTW through "Resolve" parameters you can identify the component to resolve(by name or type) and its own direct dependencies.
I have classes generated via xsd.exe (xsd.exe someschema.xsd /classes). One of the nodes is declared as an element:
<xs:element name="containsxmlelementsbeneath"/>
As the (ficticious) name implies, it looks like this:
<containsxmlelementsbeneath>
<somemore>
...
</somemore>
</containsxmlelementsbeneath>
When it is deserialized, I see in the debugger that it is of type
System.Xml.XmlNode[]
I can force it in the Immediate Window
?((System.Xml.XmlNode[])elem.containsxmlelementsbeneath)[0].InnerXml
I got no IntelliSense, which made sense when I tried the snippet in my code - the class seems to have been removed from the WinRT profile - which is nice if all you need is Windows.Data.Xml.Dom.IXmlNode - but not in this case.
How can I go and get the string representation of that element? Is there a way to "fix" the xsd.exe-generated output so it uses Windows.Data.Xml.Dom for Serialization? (doesn't look like it to me)
Did I hit a fringe case they didn't think about?
Update - tried the following (I know, an abuse of dynamic):
dynamic x = elem.containsxmlelementsbeneath;
string s = x[0].InnerXml;
This yields "The API 'System.Xml.XmlNode[]' cannot be used on the current platform."
I had a (longer) chat with another dev - after some trial and error we came up with a solution:
<xs:element ref="containsxmlelementsbeneath"/>
<xs:element name="containsxmlelementsbeneath">
</xs:element>
This creates an empty class for us (via xsd.exe)
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class containsxmlelementsbeneath
{
}
This has to be modified like this:
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class containsxmlelementsbeneath : IXmlSerializable
{
[XmlIgnore]
public string Text { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
throw new System.NotImplementedException();
}
public void ReadXml(System.Xml.XmlReader reader)
{
Text = reader.ReadInnerXml();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
throw new System.NotImplementedException();
}
}
Note that all attributes except XmlRoot have to be removed, otherwise you get Reflection Exceptions (Only XmlRoot attribute may be specified for the type containsxmlelementsbeneath. Please use XmlSchemaProviderAttribute to specify schema type.)
End Result: this node with all its subnodes as a plain old string. No non-accesible XmlNode or XmlElement any more...