I'm in a situation, where I need to do something similar to the following:
public static class mystaticclass
{
public static string filename { get; private set; }
static mystaticclass()
{
filename = "C:\\test.test";
}
}
public class myclass
{
public string filename;
public myclass(string filename)
{
this.filename = filename;
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var container = new WindsorContainer().Install(Configuration.FromXmlFile("Windsor.config"));
container.Register(Component.For<myclass>()
.DynamicParameters((k, d) =>
{
d["filename"] = mystaticclass.filename;
}));
var tmp=container.Resolve<myclass>();
}
}
however I'd very much like to configure this in the .config file, rather than in code.... is it possible?? ... probably not... so what would be a good alternative solution
N.B. the 'mystaticclass' is not something I'm able to change, however I'd like to be able to use mystaticclass2.filename in some configurations....
TIA
Sørn
Nope, not possible with XML, mostly because dynamic parameters are... well - dynamnic and that's something that can't be expressed in XML. Your case looks pretty static, so guess if you really think that's what you want you might quite easily implement support for that via IContributeComponentModelConstruction
Related
I have an Azure WebJob that will be used for Staging and Production. The keys for the proper environments are set in the app.config file.
A ConfigManager class reads the properties from the app.config file.
public static string FirstQueue
{
get { return ConfigurationManager.AppSettings["FirstQueue"]; }
}
I would like the QueueTrigger to read the from the proper queue specified in the app.config file.
public static void ProcessFirstQueue([QueueTrigger(ConfigManager.FirstQueue)] string message)
{
//some function
}
However, the QueueTrigger doesn't seem to like this. I get "An attribute argument must be a constant expression, type of expression...." Any suggestions to set this up. I do not want to hard code values in the queue trigger.
Thanks
You can resolve the queue name at runtime using the
INameResolver
Here's an example to demonstrate this:
WebJob Code:
public class Program
{
private static void Main(string[] args)
{
var config =
new JobHostConfiguration("insert connection string")
{
NameResolver = new QueueNameResolver()
};
var host = new JobHost(config);
host.RunAndBlock();
}
public static void ProcessNotification([QueueTrigger("%queueKey%")] string item)
{
//Handle message
}
public static void ProcessPoison([QueueTrigger("%queueKeyPoison%")] string item)
{
//Handle poison message
}
}
Here's the QueueNameResolver class:
public class QueueNameResolver : INameResolver
{
//name = queueKey or queueKeyPoison
public string Resolve(string name)
{
//Use the name to get it from the app.config or somewhere else.
}
}
Hope this helps,
I need to replace the DateTime serialization for JSON in WCF REST Self Hosted service. Right now, I'm using something like the following code to do it, but it's definitely not the way to go since it requires manipulating each class.
[DataContract]
public class Test
{
[IgnoreDataMember]
public DateTime StartDate;
[DataMember(Name = "StartDate")]
public string StartDateStr
{
get { return DateUtil.DateToStr(StartDate); }
set { StartDate = DateTime.Parse(value); }
}
}
where my utility function DateUtil.DateToStr does all the formatting work.
Is there any easy way to do it without having to touch the attributes on my classes which have the DataContract attribute? Ideally, there would be no attributes, but a couple of lines of code in my configuration to replace the serializer with one where I've overridden DateTime serialization.
Everything that I've found looks like I have to replace huge pieces of the pipeline.
This article doesn't appear to apply because in I'm using WebServiceHost not HttpServiceHost, which not part of the 4.5.1 Framework.
JSON.NET Serializer for WCF REST Services
By default WCF uses DataContractJsonSerializer to serialize data into JSON. Unfortunatelly date from this serializer is in very difficult format to parse by human brain.
"DateTime": "\/Date(1535481994306+0200)\/"
To override this behavior we need to write custom IDispatchMessageFormatter. This class will receive all data which should be returned to requester and change it according to our needs.
To make it happen to the operations in the endpoint add custom formatter - ClientJsonDateFormatter:
ServiceHost host=new ServiceHost(typeof(CustomService));
host.AddServiceEndpoint(typeof(ICustomContract), new WebHttpBinding(), Consts.WebHttpAddress);
foreach (var endpoint in host.Description.Endpoints)
{
if (endpoint.Address.Uri.Scheme.StartsWith("http"))
{
foreach (var operation in endpoint.Contract.Operations)
{
operation.OperationBehaviors.Add(new ClientJsonDateFormatter());
}
endpoint.Behaviors.Add(new WebHttpBehavior());
}
}
ClientJsonDateFormatter is simple class which just applies formatter ClientJsonDateFormatter
public class ClientJsonDateFormatter : IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { }
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter = new ResponseJsonFormatter(operationDescription);
}
public void Validate(OperationDescription operationDescription) { }
}
In the formatter we took imput and serialize it with the changed Serializer:
public class ResponseJsonFormatter : IDispatchMessageFormatter
{
OperationDescription Operation;
public ResponseJsonFormatter(OperationDescription operation)
{
this.Operation = operation;
}
public void DeserializeRequest(Message message, object[] parameters)
{
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
string json=Newtonsoft.Json.JsonConvert.SerializeObject(result);
byte[] bytes = Encoding.UTF8.GetBytes(json);
Message replyMessage = Message.CreateMessage(messageVersion, Operation.Messages[1].Action, new RawDataWriter(bytes));
replyMessage.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw));
return replyMessage;
}
}
And to send information to client we need data writer - RawDataWriter. Its implementation is simple:
class RawDataWriter : BodyWriter
{
byte[] data;
public RawDataWriter(byte[] data)
: base(true)
{
this.data = data;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary");
writer.WriteBase64(data, 0, data.Length);
writer.WriteEndElement();
}
}
Applying all code will result in returning date in more friendly format:
"DateTime":"2018-08-28T20:56:48.6411976+02:00"
To show it in practice I created example in the github branch DateTimeFormatter.
Please check also this answer as very likely you also will need it.
There is a limitation in JSON to convert DateTime, specially according to your case.
Please see http://msdn.microsoft.com/en-us/library/bb412170(v=vs.110).aspx
and read the section Dates/Times and JSON
To resolve this problem, I simply changed the type of serialization from JSON to XML for all the calls including DateTime.
After long time discussion ,I have find out the solution for it.
Please Use the following Code to Solve serialized date..
[IgnoreDataMember]
public DateTime? PerformanceDate { get; set; }
[DataMember(EmitDefaultValue = false, Name = "PerformanceDate")]
public string UpdateStartDateStr
{
get
{
if (this.PerformanceDate.HasValue)
return this.PerformanceDate.Value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture);
else
return null;
}
set
{
// should implement this...
}
}
I have JAXB objects created from a schema. While marshalling, the xml elements are getting annotated with ns2. I have tried all the options that exist over the net for this problem, but none of them works. I cannot modify my schema or change package-info.java. Please help
After much research and tinkering I have finally managed to achieve a solution to this problem. Please accept my apologies for not posting links to the original references - there are many and I wasn't taking notes - but this one was certainly useful.
My solution uses a filtering XMLStreamWriter which applies an empty namespace context.
public class NoNamesWriter extends DelegatingXMLStreamWriter {
private static final NamespaceContext emptyNamespaceContext = new NamespaceContext() {
#Override
public String getNamespaceURI(String prefix) {
return "";
}
#Override
public String getPrefix(String namespaceURI) {
return "";
}
#Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
};
public static XMLStreamWriter filter(Writer writer) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
#Override
public NamespaceContext getNamespaceContext() {
return emptyNamespaceContext;
}
}
You can find a DelegatingXMLStreamWriter here.
You can then filter the marshalling xml with:
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
I am sure there are more efficient mechanisms but I know this one works.
For me, only changing the package-info.java class worked like a charm, exactly as zatziky stated :
package-info.java
#javax.xml.bind.annotation.XmlSchema
(namespace = "http://example.com",
xmlns = {#XmlNs(prefix = "", namespaceURI = "http://example.com")},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;
You can let the namespaces be written only once. You will need a proxy class of the XMLStreamWriter and a package-info.java. Then you will do in your code:
StringWriter stringWriter = new StringWriter();
XMLStreamWriter writer = new Wrapper((XMLStreamWriter) XMLOutputFactory
.newInstance().createXMLStreamWriter(stringWriter));
JAXBContext jaxbContext = JAXBContext.newInstance(Collection.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(books, writer);
System.out.println(stringWriter.toString());
Proxy class (the important method is "writeNamespace"):
class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
//keeps track of what namespaces were used so that not to
//write them more than once
private List<String> namespaces = new ArrayList<String>();
public void init(){
namespaces.clear();
}
public void writeStartElement(String localName) throws XMLStreamException {
init();
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
init();
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
init();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
if(namespaces.contains(namespaceURI)){
return;
}
namespaces.add(namespaceURI);
writer.writeNamespace(prefix, namespaceURI);
}
// .. other delegation method, always the same pattern: writer.method() ...
}
package-info.java:
#XmlSchema(elementFormDefault=XmlNsForm.QUALIFIED, attributeFormDefault=XmlNsForm.UNQUALIFIED ,
xmlns = {
#XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package your.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
You can use the NamespacePrefixMapper extension to control the namespace prefixes for your use case. The same extension is supported by both the JAXB reference implementation and EclipseLink JAXB (MOXy).
http://wiki.eclipse.org/EclipseLink/Release/2.4.0/JAXB_RI_Extensions/Namespace_Prefix_Mapper
Every solution requires complex overwriting or annotations which seems not to work with recent version. I use a simpler approach, just by replacing the annoying namespaces. I wish Google & Co would use JSON and get rid of XML.
kml.marshal(file);
String kmlContent = FileUtils.readFileToString(file, "UTF-8");
kmlContent = kmlContent.replaceAll("ns2:","").replace("<kml xmlns:ns2=\"http://www.opengis.net/kml/2.2\" xmlns:ns3=\"http://www.w3.org/2005/Atom\" xmlns:ns4=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\" xmlns:ns5=\"http://www.google.com/kml/ext/2.2\">", "<kml>");
FileUtils.write(file, kmlContent, "UTF-8");
In CDI, how do I configure my beans?
Let's say I have this code:
class JawaBotApp {
private void init( String configFilePathString ) throws JawaBotException {
ConfigBean cb = new JaxbConfigPersister(configFilePathString).load();
JawaBotApp.jawaBot = JawaBot.create( cb );
}
}
class JawaBot {
public static JawaBot create( ConfigBean cb ) throws JawaBotException{
JawaBot bot = new JawaBot();
bot.applyConfig(cb);
bot.init();
return bot;
}
}
How would I convert it so both could be CDI beans?
I thought about annotating the create() with #Produces, however that would need to have it non-static, and rewrite it so the ConfigBean gets injected, which would need to rewrite JaxbConfigPersister or create a wrapper object... Too much work for nothing.
Is there better approach?
Something like:
class JawaBot {
#Inject public JavaBot(#JawaConfig String configFilePathString) {
...
}
}
Then you just need to produce an #JawaConfig String somewhere which represents your configuration. This could then be mocked out with something like an alternative or specialize to give you a diff config, or just some silly little #Producer that looks at some other external file/setting.
Then you just #Inject a JawaBot when you want it instead of all the other setup, and everything just lives in the injected constructor.
I have a static Settings class where my application can retrieve settings from. The problem is that some of these settings are strings, while others are ints or numbers. Example:
package
{
public final class Settings
{
public static function retrieve(msg:String)
{
switch (msg)
{
case "register_link":
return "http://test.com/client/register.php";
break;
case "time_limit":
return 50;
break;
}
}
}
}
Now, in the first case it should send a string and in the second a uint. However, how do I set this in the function declarement? Instead of eg. function retrieve(msg:String):String or ...:uint? If I don't set any data type, I get a warning.
HanClinto has answered your question, but I would like to also just make a note of another possible solution that keeps the return types, typed. I also find it to be a cleaner solution.
Rather than a static retrieve function, you could just use static consts, such as:
package
{
public final class Settings
{
public static const REGISTER_LINK:String = "my link";
public static const TIME_LIMIT:uint= 50;
}
}
And so forth. It's personal preference, but I thought I would throw it out there.
Use *
public static function retrieve(msg:String):*
{
if (msg == "age") {
return 23;
} else {
return "hi!";
}
}