Is it possible to pass a list of object (PhysicalComponent) to my custom service that prevent me to iterate over all PhysicalComponent ?
Actually I iterarate like this in my M2DOC template :
{m:for pc | self.eAllContents(pa::PhysicalComponent)}
{m:pc.MatrixFlow()}
{m:endfor}
You can create a service with the following signatures:
public SomeReturnType myService(List<PhysicalComponent> components) {
...
}
or
public SomeReturnType myService(Set<PhysicalComponent> components) {
...
}
or
public SomeReturnType myService(Collection<PhysicalComponent> components) {
...
}
Then you can call it this way for instance:
{m:self.eAllContents(pa::PhysicalComponent)->myService()}
The arrow tells to pass the collection to the service, the dot tell to call the service on each element of the collection.
If you used a List of a Set as the first parameter you may need to use asSequence() or asOrderedSet():
{m:self.eAllContents(pa::PhysicalComponent)->asSequence()->myService()}
or
{m:self.eAllContents(pa::PhysicalComponent)->asOrderedSet()->myService()}
Related
Current working on creating a Prism.DryIoc.Forms project to try out DryIoc (first time!).
In Xamarin.Forms there is a native DependencyService and to provide a nice way to migrate towards using Prism I would like to add it as a fallback container in case the requsted service type can't be resolved from the main container.
Current I have created a FallbackContainer and pass the instance of IContainerand overrides the methods for IResolver and delegates the rest of the IContainer calls to the instance passed during creation.
So after the default container is created and configured and then do
Container = CreateContainer();
ConfigureContainer();
Container.Rules.WithFallbackContainer(new DependencyServiceContainer(Container));
Is this the preferred method or is there any way just to attach a default IResolver?
Current implementation
public class FallbackDependencyServiceContainer : IContainer
{
private readonly IContainer container;
public FallbackDependencyServiceContainer(IContainer container)
{
this.container = container;
}
public object Resolve(Type serviceType, bool ifUnresolvedReturnDefault)
{
return ResolveFromDependencyService(serviceType);
}
public object Resolve(Type serviceType, object serviceKey, bool ifUnresolvedReturnDefault,
Type requiredServiceType,
RequestInfo preResolveParent, IScope scope)
{
return ResolveFromDependencyService(serviceType);
}
public IEnumerable<object> ResolveMany(Type serviceType, object serviceKey, Type requiredServiceType,
object compositeParentKey,
Type compositeParentRequiredType, RequestInfo preResolveParent, IScope scope)
{
return new[] { ResolveFromDependencyService(serviceType) };
}
private static object ResolveFromDependencyService(Type targetType)
{
if (!targetType.GetTypeInfo().IsInterface)
{
return null;
}
var method = typeof(DependencyService).GetTypeInfo().GetDeclaredMethod("Get");
var genericMethod = method.MakeGenericMethod(targetType);
return genericMethod.Invoke(null, new object[] { DependencyFetchTarget.GlobalInstance });
}
....
}
Thanks and looking forward to test DryIoc since I've read it's supposed to be the fastest out there
Updated answer:
You may directly use WithUnknownServiceResolvers returning DelegateFactory:
var c = new Container(Rules.Default.WithUnknownServiceResolvers(request =>
new DelegateFactory(_ => GetFromDependencyService(request.ServiceType))));
No need to implement IContainer just for that.
I think it may be optimized regarding performance by replacing DelegateFactory with ExpressionFactory. But I need some time to play with the idea.
Using DryIoc if I register two implementations of the same contract - how can control which implementation to use when using constructor injection?
I see you can you register with a key or metadata - is it possible (using an attribute?) to control with implementation is injected? Or should I require a collection and figure out the correct implementation in the ctor?
You can specify what dependency to consume in constructor via Made.Of strongly-typed spec, like so:
container.Register<SomeClient>(Made.Of(
() => new SomeClient(Arg.Of<IDep>("service key of impl")));
Here is the related SO answer with more options.
Attributed registration is supported via MEF Attributed Model:
[Export]
public class SomeClient {
public SomeClient([Import("x")]IDep dep) {}
}
[Export("x", typeof(IDep))]
public class X : IDep {}
[Export("y", typeof(IDep))]
public class Y : IDep {}
// in composition root:
using DryIoc.MefAttributedModel;
container = new Container().WithMefAttributedModel();
container.RegisterExports(
typeof(SomeClient),
typeof(X),
typeof(Y));
container.Resolve<SomeClient>(); // will inject X
I have clients passing in IDs like this: /v1/path?id=1,2,3
What I have and want
I have a resource class for Dropwizard/Jersey.
I'd like to show up the query-parameter id=1,2,3 as a List parameter in my resource's GET method
// Resource class
public List<Something> getFilteredList(#QueryParam("id") List<String> ids) {
// filter the List<Something> based on a list of ids
}
Right now, the ids list contains 1 string which is "1,2,3".
What I tried
I tried a filter but the query parameters given by Jersey's
ContainerRequestContext.getUriInfo().getQueryParameters()
is immutable.
Questions
I would like to apply a filter and change any comma separated query parameters into multi-valued parameters so that the resource method gets a list instead.
Is there a way to change the existing query parameters using a Jersey filter?
What's a good way to solve this problem?
The best way I can think of is to just create a wrapper class for the list. This makes it easier to take advantage of the specified functionality of Jersey. You can see what I mean at Passing custom type query parameter.
For example
public class IdFilter {
private List<String> ids = new ArrayList<>();
public List<String> getIds() { return ids; }
public static IdFilter valueOf(String param) {
IdFilter filter = new IdFilter();
for (String id: param.split(",") {
filter.getIds().add(id);
}
}
}
getFilteredList(#QueryParam("id") IdFilter ids) {
We don't need to do anything else. Just having the static valueOf is enough for Jersey to know how to parse the query string.
3 ways to solve it:
use the generic context-parameter UriInfo , which is not very expressive
add an explicit custom type that can parse a comma-separated list
stay with #QueryParam List<String> requiring a concatenated query like ?id=1&id=2&id=3 given as URI
I would prefer the second as most-expressive, like answered already by Paul. This way you can concisely pass a single CSV like ?id=1,2,3,3 and also use a Set to ensure unique ID values, e.g. resulting in only [1, 2, 3].
Generic context-param UriInfo
One way would be to use a generic parameter #Context UriInfo to get the list in the method's body:
public List<Something> getFilteredList( #Context UriInfo uriInfo ) {
List<String> idList = uriInfo.getQueryParameters().get("id"); // before was #QueryParam("id")
System.out.println("idList: " + idList);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> idList.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See the tutorial in Java Vogue(2015): QueryParam Annotation In Jersey -
Custom type with static valueOf(String) factory-method
The other way is to design a custom type which can be constructed using a String:
class IdSet {
Set<String> values;
// a factory method, can also be named valueOf
public static IdSet fromString(String commaSeparated) {
return new HashSet( Arrays.asList( commaSeparated.split(",") ) );
}
}
public List<Something> getFilteredList(#QueryParam("id") IdSet ids) {
System.out.println("ids (Set): " + ids.values);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> ids.values.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See Jersey's JavaDocs for #QueryParam:
The type T of the annotated parameter, field or property must either:
Be a primitive type
Have a constructor that accepts a single String argument
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String))
Have a registered implementation of ParamConverterProvider that returns a ParamConverter instance capable of a "from string" conversion for the type.
Be List<T>, Set<T> or SortedSet<T>, where T satisfies 2, 3 or 4 above. The resulting collection is read-only.
Use a collection interface with multiple key-value pairs
When the calling client uses following URI pattern: /something?id=1&id=2&id=3 then JAX-RS can deserialize them to a single parameter of List<String> id having given multiple elements:
public List<Something> getFilteredList(#QueryParam("id") List<String> ids) {
System.out.println("ids : "+ids);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> ids.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See Mkyong: JAX-RS #QueryParam example where explained the multiple occurrences of orderBy in the GET query:
#QueryParam will convert the query parameter “orderBy=age&orderBy=name” into java.util.List automatically.
See also
Handling Multiple Query Parameters in Jersey
Deserializing List<Map<String, String>> QueryParam in jersey 1
Jersey, #QueryParam List<String>
I have an adapter class for Linq-to-Sql:
public interface IAdapter : IDisposable
{
Table<Data.User> Activities { get; }
}
Data.User is an object defined by Linq-to-Sql pointing to the User table in persistence.
The implementation for this is as follows:
public class Adapter : IAdapter
{
private readonly SecretDataContext _context = new SecretDataContext();
public void Dispose()
{
_context.Dispose();
}
public Table<Data.User> Users
{
get { return _context.Users; }
}
}
This makes mocking the persistence layer easy in unit testing, as I can just return whatever collection of data I want for Users (Rhino.Mocks):
Expect.Call(_adapter.Users).Return(users);
The problem is that I cannot create the object 'users' since the constructors are not accessible and the class Table is sealed. One option I tried is to just make IAdapter return IEnumerable or IQueryable, but the problem there is that I then do not have access to the methods ITable provides (e.g. InsertOnSubmit()). Is there a way I can create the fake Table in the unit test scenario so that I may be a happy TDD developer?
My current solution is to wrap the functionality I want from Table into a TableWrapper class:
public interface ITableWrapper<TEntity>
where TEntity : class
{
IEnumerable<TEntity> Collection { get; }
void InsertOnSubmit(TEntity entity);
}
And here's the implementation:
public class TableWrapper<TEntity> : ITableWrapper<TEntity>
where TEntity : class
{
private readonly Table<TEntity> _table;
public TableWrapper(Table<TEntity> table)
{
_table = table;
}
public IEnumerable<TEntity> Collection
{
get { return _table; }
}
public void InsertOnSubmit(TEntity entity)
{
_table.InsertOnSubmit(entity);
}
}
So now I can easily mock data from Collection, as well as keeping the functionality of InsertOnSubmit (any other functions that I need down the road can be added later on).
I have had success using the Data Access Layer to produce domain object collections and then using linq to objects.
The object under test then only relates to List, which is fairly easy to unit test.
I don't like when the logic entities should have Data Access Layer dependencies. They should stop at the service layer, if even there. I usually go for the model where the service layer invokes a data access object to get a List, passes that list into whichever logic object that needs it (if necessary uses linq-to-objects to filter out the relevant data and injects it into eiter a flat list, dictionary or an object model).
The business objects become very testable, even though they don't benefit from the richness of the inferred data model.
I have a web application that uses the Web Service created in ASP.NET. In this, web service I want to pass an collection object of Key Value type (i.e. something like Hashtable or Dictionay).
But we cannot use objects that implements from IDictionary.
I do not want to create a serialized class in my web service.
Can anyone suggest me the best approach for this?
dev.e.loper is almost right. You can use a List<Pair>.
Alternatively, you can use List<KeyValuePair<TKey,TValue>>.
MSDN Documentation:
KeyValuePair
Pair
I'm not totally clear on your question, but maybe you are needing something like this?
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
{
return;
}
while (reader.NodeType != XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
var key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
var value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
foreach (var key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
You can inherit from KeyedCollection which is Serializable.
http://msdn.microsoft.com/en-us/library/ms132438.aspx
I solved this by using DictionaryEntry
The only difference is that Key is Object as well.
I basically have a Dictionary ToDictionary(DictionaryEntry[] entries) and a DictionaryEntry[] FromDictionary(Dictionary entries) static methods which are very light weight and end up getting me to the same place without having to make my own collection class.
The added benefit is that the XML which comes as a result is closer to that in which the WCF Web Services use by default! That means you can make this change now in your client code and be ready for WCF if you decide to move that way.
The result looks like this over JSON [{"Key": key1, "Value": value1}, {"Key": key2, "Value": value2}] exactly the same as it does over WCF by default.
You could try to use 2 arrays, 1 for keys and one for values, where the indexes of the arrays match up. Not the most ideal solution but a valid one. The internals of the webservice you can use IDictionary and just pass out the Keys and Values of that object.